#!/usr/libexec/platform-python
from __future__ import print_function
import os
import sys
curdir = os.path.dirname(sys.argv[0])
gendir = os.path.join(curdir, '../../../../libglusterfs/src')
sys.path.append(gendir)
from generator import ops, fop_subs, cbk_subs, generate
FD_DATA_MODIFYING_OP_FOP_TEMPLATE = """
int32_t
cs_@NAME@ (call_frame_t *frame, xlator_t *this,
@LONG_ARGS@)
{
int op_errno = EINVAL ;
cs_local_t *local = NULL;
int ret = 0;
cs_inode_ctx_t *ctx = NULL;
gf_cs_obj_state state = -1;
VALIDATE_OR_GOTO (frame, err);
VALIDATE_OR_GOTO (this, err);
VALIDATE_OR_GOTO (fd, err);
local = cs_local_init (this, frame, NULL, fd, GF_FOP_@UPNAME@);
if (!local) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "local init failed");
op_errno = ENOMEM;
goto err;
}
__cs_inode_ctx_get (this, fd->inode, &ctx);
if (ctx)
state = __cs_get_file_state (this, fd->inode, ctx);
else
state = GF_CS_LOCAL;
xdata = xdata ? dict_ref (xdata) : dict_new ();
if (!xdata) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
op_errno = ENOMEM;
goto err;
}
local->xattr_req = xdata;
ret = dict_set_uint32 (local->xattr_req, GF_CS_OBJECT_STATUS, 1);
if (ret) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "dict_set failed key:"
" %s", GF_CS_OBJECT_STATUS);
goto err;
}
local->stub = fop_@NAME@_stub (frame, cs_resume_@NAME@,
@SHORT_ARGS@);
if (!local->stub) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
op_errno = ENOMEM;
goto err;
}
if (state == GF_CS_LOCAL) {
STACK_WIND (frame, cs_@NAME@_cbk,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->@NAME@,
@SHORT_ARGS@);
} else {
local->call_cnt++;
ret = locate_and_execute (frame);
if (ret) {
op_errno = ENOMEM;
goto err;
}
}
return 0;
err:
CS_STACK_UNWIND (@NAME@, frame, -1, op_errno, @CBK_ERROR_ARGS@);
return 0;
}
"""
FD_DATA_MODIFYING_RESUME_OP_FOP_TEMPLATE = """
int32_t
cs_resume_@NAME@ (call_frame_t *frame, xlator_t *this,
@LONG_ARGS@)
{
int ret = 0;
ret = cs_resume_postprocess (this, frame, fd->inode);
if (ret) {
goto unwind;
}
cs_inodelk_unlock (frame);
STACK_WIND (frame, cs_@NAME@_cbk,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->@NAME@,
@SHORT_ARGS@);
return 0;
unwind:
cs_inodelk_unlock (frame);
cs_common_cbk (frame);
return 0;
}
"""
FD_DATA_MODIFYING_OP_FOP_CBK_TEMPLATE = """
int32_t
cs_@NAME@_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@LONG_ARGS@)
{
cs_local_t *local = NULL;
int ret = 0;
uint64_t val = 0;
fd_t *fd = NULL;
local = frame->local;
fd = local->fd;
/* Do we need lock here? */
local->call_cnt++;
if (op_ret == -1) {
ret = dict_get_uint64 (xdata, GF_CS_OBJECT_STATUS, &val);
if (ret == 0) {
if (val == GF_CS_ERROR) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0,
"could not get file state, unwinding");
op_ret = -1;
op_errno = EIO;
goto unwind;
} else {
__cs_inode_ctx_update (this, fd->inode, val);
gf_msg (this->name, GF_LOG_INFO, 0, 0,
" state = %" PRIu64, val);
if (local->call_cnt == 1 &&
(val == GF_CS_REMOTE ||
val == GF_CS_DOWNLOADING)) {
gf_msg (this->name, GF_LOG_INFO, 0,
0, " will repair and download "
"the file, current state : %"
PRIu64, val);
goto repair;
} else {
gf_msg (this->name, GF_LOG_ERROR, 0, 0,
"second @NAME@, Unwinding");
goto unwind;
}
}
} else {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "file state "
"could not be figured, unwinding");
goto unwind;
}
} else {
/* successful @NAME@ => file is local */
__cs_inode_ctx_update (this, fd->inode, GF_CS_LOCAL);
gf_msg (this->name, GF_LOG_INFO, 0, 0, "state : GF_CS_LOCAL"
", @NAME@ successful");
goto unwind;
}
repair:
ret = locate_and_execute (frame);
if (ret) {
goto unwind;
}
return 0;
unwind:
CS_STACK_UNWIND (@NAME@, frame, op_ret, op_errno, @SHORT_ARGS@);
return 0;
}
"""
LOC_STAT_OP_FOP_TEMPLATE = """
int32_t
cs_@NAME@ (call_frame_t *frame, xlator_t *this,
@LONG_ARGS@)
{
int op_errno = EINVAL;
cs_local_t *local = NULL;
int ret = 0;
local = cs_local_init (this, frame, loc, NULL, GF_FOP_@UPNAME@);
if (!local) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "local is NULL");
op_errno = ENOMEM;
goto err;
}
if (loc->inode->ia_type == IA_IFDIR)
goto wind;
xdata = xdata ? dict_ref (xdata) : dict_new ();
if (!xdata) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
op_errno = ENOMEM;
goto err;
}
local->xattr_req = xdata;
ret = dict_set_uint32 (local->xattr_req, GF_CS_OBJECT_STATUS, 1);
if (ret) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0, "dict_set failed key:"
" %s", GF_CS_OBJECT_STATUS);
goto err;
}
wind:
STACK_WIND (frame, cs_@NAME@_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->@NAME@,
@SHORT_ARGS@);
return 0;
err:
CS_STACK_UNWIND (@NAME@, frame, -1, op_errno, @CBK_ERROR_ARGS@);
return 0;
}
"""
LOC_STAT_OP_FOP_CBK_TEMPLATE = """
int32_t
cs_@NAME@_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@LONG_ARGS@)
{
int ret = 0;
uint64_t val = 0;
loc_t *loc = NULL;
cs_local_t *local = NULL;
local = frame->local;
loc = &local->loc;
if (op_ret == 0) {
ret = dict_get_uint64 (xdata, GF_CS_OBJECT_STATUS, &val);
if (!ret) {
ret = __cs_inode_ctx_update (this, loc->inode, val);
if (ret) {
gf_msg (this->name, GF_LOG_ERROR, 0, 0,
"ctx update failed");
}
}
} else {
cs_inode_ctx_reset (this, loc->inode);
}
CS_STACK_UNWIND (@NAME@, frame, op_ret, op_errno, @SHORT_ARGS@);
return 0;
}
"""
# All xlator FOPs are covered in the following section just to create a clarity
# The lists themselves are not used.
entry_ops = ['mknod', 'mkdir', 'unlink', 'rmdir', 'symlink', 'rename', 'link',
'create']
special_ops = ['statfs', 'lookup', 'ipc', 'compound', 'icreate', 'namelink']
ignored_ops = ['getspec']
inode_ops = ['stat', 'readlink', 'truncate', 'open', 'setxattr', 'getxattr',
'removexattr', 'opendir', 'access', 'inodelk', 'entrylk',
'xattrop', 'setattr', 'lease', 'getactivelk', 'setactivelk',
'discover']
fd_ops = ['readv', 'writev', 'flush', 'fsync', 'fsyncdir', 'ftruncate',
'fstat', 'lk', 'readdir', 'finodelk', 'fentrylk', 'fxattrop',
'fsetxattr', 'fgetxattr', 'rchecksum', 'fsetattr', 'readdirp',
'fremovexattr', 'fallocate', 'discard', 'zerofill', 'seek']
# These are the current actual lists used to generate the code
# The following list contains fops which are fd based that modifies data
fd_data_modify_op_fop_template = ['writev', 'flush', 'fsync',
'ftruncate', 'rchecksum', 'fallocate',
'discard', 'zerofill', 'seek']
# The following list contains fops which are entry based that does not change
# data
loc_stat_op_fop_template = ['lookup', 'stat', 'discover', 'access', 'setattr',
'getattr']
# These fops need a separate implementation
special_fops = ['statfs', 'setxattr', 'unlink', 'getxattr',
'truncate', 'fstat', 'readv', 'readdirp']
def gen_defaults():
for name in ops:
if name in fd_data_modify_op_fop_template:
print(generate(FD_DATA_MODIFYING_OP_FOP_CBK_TEMPLATE, name, cbk_subs))
print(generate(FD_DATA_MODIFYING_RESUME_OP_FOP_TEMPLATE, name, fop_subs))
print(generate(FD_DATA_MODIFYING_OP_FOP_TEMPLATE, name, fop_subs))
elif name in loc_stat_op_fop_template:
print(generate(LOC_STAT_OP_FOP_CBK_TEMPLATE, name, cbk_subs))
print(generate(LOC_STAT_OP_FOP_TEMPLATE, name, fop_subs))
for l in open(sys.argv[1], 'r').readlines():
if l.find('#pragma generate') != -1:
print("/* BEGIN GENERATED CODE - DO NOT MODIFY */")
gen_defaults()
print("/* END GENERATED CODE */")
else:
print(l[:-1])