src/dbfs/fileop.c
author Tero Marttila <terom@fixme.fi>
Tue, 21 Oct 2008 21:42:17 +0300
changeset 36 56427f22e969
parent 35 4f10421681d2
child 40 03017f5f0087
permissions -rw-r--r--
tweak debug/info output, implement dbfs_unlink with slightly improved error macros handling
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
#include <stdlib.h>
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     2
#include <assert.h>
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     3
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     4
#include <postgresql/libpq/libpq-fs.h>
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
#include "dbfs.h"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
#include "op_base.h"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     8
#include "../lib/log.h"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    10
struct dbfs_fileop {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    11
    struct dbfs_op base;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    12
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    13
    uint32_t lo_fd;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
};
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    15
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    16
static void _dbfs_fileop_free (struct dbfs_op *op_base) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    17
    struct dbfs_fileop *fop = (struct dbfs_fileop *) op_base;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    18
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    19
    /* no-op */
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    20
    (void) fop;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    21
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    22
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    23
static void dbfs_open_res (const struct evsql_result_info *res, void *arg) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    24
    struct dbfs_fileop *fop = arg;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    25
    int err;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    26
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    27
    // check the results
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    28
    if ((err = _dbfs_check_res(res, 1, 2)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    29
        SERROR(err = (err ==  1 ? ENOENT : EIO));
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    31
    const char *type;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    32
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    33
    // extract the data
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    34
    if (0
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    35
        ||  evsql_result_string(res, 0, 0, &type,           0 ) // inodes.type
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    36
        ||  evsql_result_uint32(res, 0, 1, &fop->lo_fd,     0 ) // fd
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    37
    )
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    38
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    39
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    40
    // is it a dir?
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    41
    if (_dbfs_mode(type) != S_IFREG)
35
4f10421681d2 working mknod, mkdir, symlink
Tero Marttila <terom@fixme.fi>
parents: 31
diff changeset
    42
        EERROR(err = EINVAL, "wrong type: %s", type);
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    43
    
36
56427f22e969 tweak debug/info output, implement dbfs_unlink with slightly improved error macros handling
Tero Marttila <terom@fixme.fi>
parents: 35
diff changeset
    44
    INFO("\t[dbfs.open %p:%p] -> ino=%lu, type=%s", fop, fop->base.req, (unsigned long int) fop->base.ino, type);
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    45
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    46
    // open_fn done, do the open_reply
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    47
    if ((err = dbfs_op_open_reply(&fop->base)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    48
        goto error;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    49
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    50
    // success, fallthrough for evsql_result_free
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    51
    err = 0;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    52
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    53
error:
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    54
    if (err)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    55
        // fail it
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    56
        dbfs_op_fail(&fop->base, err);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    57
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    58
    // free
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    59
    evsql_result_free(res);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    60
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    61
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    62
static void dbfs_fileop_open (struct dbfs_op *op_base) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    63
    struct dbfs_fileop *fop = (struct dbfs_fileop *) op_base;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    64
    struct dbfs *ctx = fuse_req_userdata(fop->base.req);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    65
    int err;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    66
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    67
    // make sure the file actually exists
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    68
    const char *sql =
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    69
        "SELECT"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    70
        " inodes.type, lo_open(inodes.data, $1::int4) AS fd"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    71
        " FROM inodes"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    72
        " WHERE inodes.ino = $2::int4";
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    73
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    74
    static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    75
        EVSQL_PARAM ( UINT32 ),
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    76
        EVSQL_PARAM ( UINT32 ),
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    77
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    78
        EVSQL_PARAMS_END
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    79
    };
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    80
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    81
    // build params
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    82
    if (0
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    83
        ||  evsql_param_uint32(&params, 0, INV_READ | INV_WRITE)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    84
        ||  evsql_param_uint32(&params, 1, fop->base.ino)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    85
    )
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    86
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    87
        
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    88
    // query
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    89
    if (evsql_query_params(ctx->db, fop->base.trans, sql, &params, dbfs_open_res, fop) == NULL)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    90
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    91
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    92
    // ok, wait for the info results
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    93
    return;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    94
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    95
error:
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    96
    // fail it
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    97
    dbfs_op_fail(&fop->base, err);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    98
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    99
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   100
void dbfs_open (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   101
    struct dbfs *ctx = fuse_req_userdata(req);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   102
    struct dbfs_fileop *fop = NULL;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   103
    int err;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   104
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   105
    // allocate it
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   106
    if ((fop = calloc(1, sizeof(*fop))) == NULL && (err = EIO))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   107
        ERROR("calloc");
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   108
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   109
    // do the op_open
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   110
    if ((err = dbfs_op_open(ctx, &fop->base, req, ino, fi, _dbfs_fileop_free, dbfs_fileop_open)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   111
        ERROR("dbfs_op_open");
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   112
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   113
    // log
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   114
    INFO("[dbfs.open %p:%p] ino=%lu, fi->flags=%04X", fop, req, ino, fi->flags);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   115
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   116
    // wait
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   117
    return;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   118
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   119
error:
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   120
    if (fop) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   121
        // we can fail normally
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   122
        dbfs_op_fail(&fop->base, err);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   123
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   124
    } else {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   125
        // must error out manually as we couldn't alloc the context
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   126
        if ((err = fuse_reply_err(req, err)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   127
            EWARNING(err, "fuse_reply_err");
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   128
    }
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   129
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   130
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   131
void dbfs_read_res (const struct evsql_result_info *res, void *arg) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   132
    struct dbfs_fileop *fop = arg;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   133
    int err;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   134
    const char *buf;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
    size_t size;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136
 
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   137
    // check the results
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   138
    if ((err = _dbfs_check_res(res, 1, 1)) < 0)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   139
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   140
        
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   141
    // get the data
31
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   142
    if (evsql_result_binary(res, 0, 0, &buf, &size, 0))
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   143
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   144
36
56427f22e969 tweak debug/info output, implement dbfs_unlink with slightly improved error macros handling
Tero Marttila <terom@fixme.fi>
parents: 35
diff changeset
   145
    INFO("\t[dbfs.read %p:%p] -> size=%zu", fop, fop->base.req, size);
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   146
        
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   147
    // send it
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   148
    if ((err = fuse_reply_buf(fop->base.req, buf, size)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   149
        EERROR(err, "fuse_reply_buf");
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   150
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   151
    // ok, req handled
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   152
    if ((err = dbfs_op_req_done(&fop->base)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   153
        goto error;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   154
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   155
    // good, fallthrough
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   156
    err = 0;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   157
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   158
error:
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   159
    if (err)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   160
        dbfs_op_fail(&fop->base, err);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   161
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   162
    // free
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   163
    evsql_result_free(res);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   164
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   165
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   166
void dbfs_read (struct fuse_req *req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   167
    struct dbfs *ctx = fuse_req_userdata(req);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   168
    struct dbfs_fileop *fop;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   169
    int err;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   170
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   171
    // get the op
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   172
    if ((fop = (struct dbfs_fileop *) dbfs_op_req(req, ino, fi)) == NULL)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   173
        return;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   174
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   175
    // log
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   176
    INFO("[dbfs.read %p:%p] ino=%lu, size=%zu, off=%lu, fi->flags=%04X", fop, req, ino, size, off, fi->flags);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   177
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   178
    // query
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   179
    const char *sql = 
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   180
        "SELECT"
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   181
        " lo_pread($1::int4, $2::int4, $3::int4)";
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   182
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   183
    static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   184
        EVSQL_PARAM ( UINT32 ), // fd
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   185
        EVSQL_PARAM ( UINT32 ), // len
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   186
        EVSQL_PARAM ( UINT32 ), // off
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   187
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   188
        EVSQL_PARAMS_END
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   189
    };
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   190
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   191
    // build params
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   192
    if (0
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   193
        ||  evsql_param_uint32(&params, 0, fop->lo_fd)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   194
        ||  evsql_param_uint32(&params, 1, size)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   195
        ||  evsql_param_uint32(&params, 2, off)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   196
    )
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   197
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   198
        
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   199
    // query
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   200
    if (evsql_query_params(ctx->db, fop->base.trans, sql, &params, dbfs_read_res, fop) == NULL)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   201
        SERROR(err = EIO);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   202
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   203
    // ok, wait for the info results
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   204
    return;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   205
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   206
error:
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   207
    // fail it
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   208
    dbfs_op_fail(&fop->base, err);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   209
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   210
31
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   211
void dbfs_write_res (const struct evsql_result_info *res, void *arg) {
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   212
    struct dbfs_fileop *fop = arg;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   213
    int err;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   214
    uint32_t size;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   215
 
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   216
    // check the results
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   217
    if ((err = _dbfs_check_res(res, 1, 1)) < 0)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   218
        SERROR(err = EIO);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   219
        
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   220
    // get the size
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   221
    if (evsql_result_uint32(res, 0, 0, &size, 0))
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   222
        SERROR(err = EIO);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   223
36
56427f22e969 tweak debug/info output, implement dbfs_unlink with slightly improved error macros handling
Tero Marttila <terom@fixme.fi>
parents: 35
diff changeset
   224
    INFO("\t[dbfs.write %p:%p] -> size=%lu", fop, fop->base.req, (long unsigned int) size);
31
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   225
        
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   226
    // send it
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   227
    if ((err = fuse_reply_write(fop->base.req, size)))
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   228
        EERROR(err, "fuse_reply_write");
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   229
    
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   230
    // ok, req handled
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   231
    if ((err = dbfs_op_req_done(&fop->base)))
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   232
        goto error;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   233
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   234
    // good, fallthrough
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   235
    err = 0;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   236
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   237
error:
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   238
    if (err)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   239
        dbfs_op_fail(&fop->base, err);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   240
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   241
    // free
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   242
    evsql_result_free(res);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   243
}
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   244
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   245
void dbfs_write (struct fuse_req *req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi) {
31
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   246
    struct dbfs *ctx = fuse_req_userdata(req);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   247
    struct dbfs_fileop *fop;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   248
    int err;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   249
    
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   250
    // get the op
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   251
    if ((fop = (struct dbfs_fileop *) dbfs_op_req(req, ino, fi)) == NULL)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   252
        return;
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   253
31
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   254
    // log
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   255
    INFO("[dbfs.write %p:%p] ino=%lu, size=%zu, off=%lu, fi->flags=%04X", fop, req, ino, size, off, fi->flags);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   256
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   257
    // query
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   258
    const char *sql = 
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   259
        "SELECT"
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   260
        " lo_pwrite($1::int4, $2::bytea, $3::int4)";
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   261
    
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   262
    static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   263
        EVSQL_PARAM ( UINT32 ), // fd
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   264
        EVSQL_PARAM ( BINARY ), // buf
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   265
        EVSQL_PARAM ( UINT32 ), // off
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   266
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   267
        EVSQL_PARAMS_END
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   268
    };
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   269
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   270
    // build params
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   271
    if (0
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   272
        ||  evsql_param_uint32(&params, 0, fop->lo_fd)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   273
        ||  evsql_param_binary(&params, 1, buf, size)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   274
        ||  evsql_param_uint32(&params, 2, off)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   275
    )
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   276
        SERROR(err = EIO);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   277
        
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   278
    // query
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   279
    if (evsql_query_params(ctx->db, fop->base.trans, sql, &params, dbfs_write_res, fop) == NULL)
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   280
        SERROR(err = EIO);
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   281
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   282
    // ok, wait for the info results
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   283
    return;
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   284
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   285
error:
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   286
    // fail it
7804cd7b5cd5 write+setattr
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   287
    dbfs_op_fail(&fop->base, err);
30
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   288
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   289
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   290
void dbfs_flush (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   291
    struct dbfs_fileop *fop;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   292
    int err;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   293
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   294
    // get the fop
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   295
    if ((fop = (struct dbfs_fileop *) dbfs_op_req(req, ino, fi)) == NULL)
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   296
        return;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   297
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   298
    // log
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   299
    INFO("[dbfs.flush %p:%p] ino=%lu", fop, req, ino);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   300
    
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   301
    // and reply...
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   302
    if ((err = fuse_reply_err(req, 0)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   303
        EWARNING(err, "fuse_reply_err");
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   304
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   305
    // done
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   306
    if ((err = dbfs_op_req_done(&fop->base)))
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   307
        goto error;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   308
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   309
    // good
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   310
    return;
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   311
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   312
error:
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   313
    dbfs_op_fail(&fop->base, err);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   314
}
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   315
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   316
void dbfs_release (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi) {
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   317
    // just passthrough to dbfs_op
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   318
    // the lo_fd will be closed automatically
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   319
    dbfs_op_release(req, ino, fi);
d8fabd347a8e working open+read+flush+release
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   320
}