blob: b082c08cef596b46b9afb56843be2ca1fe5d3316 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hdfs_http_query.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#define PERM_STR_LEN 4 // "644" + one byte for NUL
#define SHORT_STR_LEN 6 // 65535 + NUL
#define LONG_STR_LEN 21 // 2^64-1 = 18446744073709551615 + NUL
/**
* Create query based on NameNode hostname,
* NameNode port, path, operation and other parameters
*
* @param host NameNode hostName
* @param nnPort Port of NameNode
* @param path Absolute path for the corresponding file
* @param op Operations
* @param paraNum Number of remaining parameters
* @param paraNames Names of remaining parameters
* @param paraValues Values of remaining parameters
* @param url Holding the created URL
* @return 0 on success and non-zero value to indicate error
*/
static int createQueryURL(const char *host, unsigned int nnPort,
const char *path, const char *op, int paraNum,
const char **paraNames, const char **paraValues,
char **queryUrl)
{
size_t length = 0;
int i = 0, offset = 0, ret = 0;
char *url = NULL;
const char *protocol = "http://";
const char *prefix = "/webhdfs/v1";
if (!paraNames || !paraValues) {
return EINVAL;
}
length = strlen(protocol) + strlen(host) + strlen(":") +
SHORT_STR_LEN + strlen(prefix) + strlen(path) +
strlen ("?op=") + strlen(op);
for (i = 0; i < paraNum; i++) {
if (paraNames[i] && paraValues[i]) {
length += 2 + strlen(paraNames[i]) + strlen(paraValues[i]);
}
}
url = malloc(length); // The '\0' has already been included
// when using SHORT_STR_LEN
if (!url) {
return ENOMEM;
}
offset = snprintf(url, length, "%s%s:%d%s%s?op=%s",
protocol, host, nnPort, prefix, path, op);
if (offset >= length || offset < 0) {
ret = EIO;
goto done;
}
for (i = 0; i < paraNum; i++) {
if (!paraNames[i] || !paraValues[i] || paraNames[i][0] == '\0' ||
paraValues[i][0] == '\0') {
continue;
}
offset += snprintf(url + offset, length - offset,
"&%s=%s", paraNames[i], paraValues[i]);
if (offset >= length || offset < 0) {
ret = EIO;
goto done;
}
}
done:
if (ret) {
free(url);
return ret;
}
*queryUrl = url;
return 0;
}
int createUrlForMKDIR(const char *host, int nnPort,
const char *path, const char *user, char **url)
{
const char *userPara = "user.name";
return createQueryURL(host, nnPort, path, "MKDIRS", 1,
&userPara, &user, url);
}
int createUrlForGetFileStatus(const char *host, int nnPort, const char *path,
const char *user, char **url)
{
const char *userPara = "user.name";
return createQueryURL(host, nnPort, path, "GETFILESTATUS", 1,
&userPara, &user, url);
}
int createUrlForLS(const char *host, int nnPort, const char *path,
const char *user, char **url)
{
const char *userPara = "user.name";
return createQueryURL(host, nnPort, path, "LISTSTATUS",
1, &userPara, &user, url);
}
int createUrlForNnAPPEND(const char *host, int nnPort, const char *path,
const char *user, char **url)
{
const char *userPara = "user.name";
return createQueryURL(host, nnPort, path, "APPEND",
1, &userPara, &user, url);
}
int createUrlForMKDIRwithMode(const char *host, int nnPort, const char *path,
int mode, const char *user, char **url)
{
int strlength;
char permission[PERM_STR_LEN];
const char *paraNames[2], *paraValues[2];
paraNames[0] = "permission";
paraNames[1] = "user.name";
memset(permission, 0, PERM_STR_LEN);
strlength = snprintf(permission, PERM_STR_LEN, "%o", mode);
if (strlength < 0 || strlength >= PERM_STR_LEN) {
return EIO;
}
paraValues[0] = permission;
paraValues[1] = user;
return createQueryURL(host, nnPort, path, "MKDIRS", 2,
paraNames, paraValues, url);
}
int createUrlForRENAME(const char *host, int nnPort, const char *srcpath,
const char *destpath, const char *user, char **url)
{
const char *paraNames[2], *paraValues[2];
paraNames[0] = "destination";
paraNames[1] = "user.name";
paraValues[0] = destpath;
paraValues[1] = user;
return createQueryURL(host, nnPort, srcpath,
"RENAME", 2, paraNames, paraValues, url);
}
int createUrlForCHMOD(const char *host, int nnPort, const char *path,
int mode, const char *user, char **url)
{
int strlength;
char permission[PERM_STR_LEN];
const char *paraNames[2], *paraValues[2];
paraNames[0] = "permission";
paraNames[1] = "user.name";
memset(permission, 0, PERM_STR_LEN);
strlength = snprintf(permission, PERM_STR_LEN, "%o", mode);
if (strlength < 0 || strlength >= PERM_STR_LEN) {
return EIO;
}
paraValues[0] = permission;
paraValues[1] = user;
return createQueryURL(host, nnPort, path, "SETPERMISSION",
2, paraNames, paraValues, url);
}
int createUrlForDELETE(const char *host, int nnPort, const char *path,
int recursive, const char *user, char **url)
{
const char *paraNames[2], *paraValues[2];
paraNames[0] = "recursive";
paraNames[1] = "user.name";
if (recursive) {
paraValues[0] = "true";
} else {
paraValues[0] = "false";
}
paraValues[1] = user;
return createQueryURL(host, nnPort, path, "DELETE",
2, paraNames, paraValues, url);
}
int createUrlForCHOWN(const char *host, int nnPort, const char *path,
const char *owner, const char *group,
const char *user, char **url)
{
const char *paraNames[3], *paraValues[3];
paraNames[0] = "owner";
paraNames[1] = "group";
paraNames[2] = "user.name";
paraValues[0] = owner;
paraValues[1] = group;
paraValues[2] = user;
return createQueryURL(host, nnPort, path, "SETOWNER",
3, paraNames, paraValues, url);
}
int createUrlForOPEN(const char *host, int nnPort, const char *path,
const char *user, size_t offset, size_t length, char **url)
{
int strlength;
char offsetStr[LONG_STR_LEN], lengthStr[LONG_STR_LEN];
const char *paraNames[3], *paraValues[3];
paraNames[0] = "offset";
paraNames[1] = "length";
paraNames[2] = "user.name";
memset(offsetStr, 0, LONG_STR_LEN);
memset(lengthStr, 0, LONG_STR_LEN);
strlength = snprintf(offsetStr, LONG_STR_LEN, "%lu", offset);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
strlength = snprintf(lengthStr, LONG_STR_LEN, "%lu", length);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
paraValues[0] = offsetStr;
paraValues[1] = lengthStr;
paraValues[2] = user;
return createQueryURL(host, nnPort, path, "OPEN",
3, paraNames, paraValues, url);
}
int createUrlForUTIMES(const char *host, int nnPort, const char *path,
long unsigned mTime, long unsigned aTime,
const char *user, char **url)
{
int strlength;
char modTime[LONG_STR_LEN], acsTime[LONG_STR_LEN];
const char *paraNames[3], *paraValues[3];
memset(modTime, 0, LONG_STR_LEN);
memset(acsTime, 0, LONG_STR_LEN);
strlength = snprintf(modTime, LONG_STR_LEN, "%lu", mTime);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
strlength = snprintf(acsTime, LONG_STR_LEN, "%lu", aTime);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
paraNames[0] = "modificationtime";
paraNames[1] = "accesstime";
paraNames[2] = "user.name";
paraValues[0] = modTime;
paraValues[1] = acsTime;
paraValues[2] = user;
return createQueryURL(host, nnPort, path, "SETTIMES",
3, paraNames, paraValues, url);
}
int createUrlForNnWRITE(const char *host, int nnPort,
const char *path, const char *user,
int16_t replication, size_t blockSize, char **url)
{
int strlength;
char repStr[SHORT_STR_LEN], blockSizeStr[LONG_STR_LEN];
const char *paraNames[4], *paraValues[4];
memset(repStr, 0, SHORT_STR_LEN);
memset(blockSizeStr, 0, LONG_STR_LEN);
if (replication > 0) {
strlength = snprintf(repStr, SHORT_STR_LEN, "%u", replication);
if (strlength < 0 || strlength >= SHORT_STR_LEN) {
return EIO;
}
}
if (blockSize > 0) {
strlength = snprintf(blockSizeStr, LONG_STR_LEN, "%lu", blockSize);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
}
paraNames[0] = "overwrite";
paraNames[1] = "replication";
paraNames[2] = "blocksize";
paraNames[3] = "user.name";
paraValues[0] = "true";
paraValues[1] = repStr;
paraValues[2] = blockSizeStr;
paraValues[3] = user;
return createQueryURL(host, nnPort, path, "CREATE",
4, paraNames, paraValues, url);
}
int createUrlForSETREPLICATION(const char *host, int nnPort,
const char *path, int16_t replication,
const char *user, char **url)
{
char repStr[SHORT_STR_LEN];
const char *paraNames[2], *paraValues[2];
int strlength;
memset(repStr, 0, SHORT_STR_LEN);
if (replication > 0) {
strlength = snprintf(repStr, SHORT_STR_LEN, "%u", replication);
if (strlength < 0 || strlength >= SHORT_STR_LEN) {
return EIO;
}
}
paraNames[0] = "replication";
paraNames[1] = "user.name";
paraValues[0] = repStr;
paraValues[1] = user;
return createQueryURL(host, nnPort, path, "SETREPLICATION",
2, paraNames, paraValues, url);
}
int createUrlForGetBlockLocations(const char *host, int nnPort,
const char *path, size_t offset,
size_t length, const char *user, char **url)
{
char offsetStr[LONG_STR_LEN], lengthStr[LONG_STR_LEN];
const char *paraNames[3], *paraValues[3];
int strlength;
memset(offsetStr, 0, LONG_STR_LEN);
memset(lengthStr, 0, LONG_STR_LEN);
if (offset > 0) {
strlength = snprintf(offsetStr, LONG_STR_LEN, "%lu", offset);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
}
if (length > 0) {
strlength = snprintf(lengthStr, LONG_STR_LEN, "%lu", length);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
}
paraNames[0] = "offset";
paraNames[1] = "length";
paraNames[2] = "user.name";
paraValues[0] = offsetStr;
paraValues[1] = lengthStr;
paraValues[2] = user;
return createQueryURL(host, nnPort, path, "GET_BLOCK_LOCATIONS",
3, paraNames, paraValues, url);
}
int createUrlForReadFromDatanode(const char *dnHost, int dnPort,
const char *path, size_t offset,
size_t length, const char *user,
const char *namenodeRpcAddr, char **url)
{
char offsetStr[LONG_STR_LEN], lengthStr[LONG_STR_LEN];
const char *paraNames[4], *paraValues[4];
int strlength;
memset(offsetStr, 0, LONG_STR_LEN);
memset(lengthStr, 0, LONG_STR_LEN);
if (offset > 0) {
strlength = snprintf(offsetStr, LONG_STR_LEN, "%lu", offset);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
}
if (length > 0) {
strlength = snprintf(lengthStr, LONG_STR_LEN, "%lu", length);
if (strlength < 0 || strlength >= LONG_STR_LEN) {
return EIO;
}
}
paraNames[0] = "offset";
paraNames[1] = "length";
paraNames[2] = "user.name";
paraNames[3] = "namenoderpcaddress";
paraValues[0] = offsetStr;
paraValues[1] = lengthStr;
paraValues[2] = user;
paraValues[3] = namenodeRpcAddr;
return createQueryURL(dnHost, dnPort, path, "OPEN",
4, paraNames, paraValues, url);
}