END_TEST START_TEST(test_append) { bool s; struct hdfs_object *e = NULL, *lb; const char *tf = "/HADOOFUS_TEST_APPEND", *client = "HADOOFUS_CLIENT"; // Create the file first hdfs_create(h, tf, 0644, client, true/*overwrite*/, false/*createparent*/, 1/*replication*/, 64*1024*1024, &e); if (e) ck_abort_msg("exception: %s", hdfs_exception_get_message(e)); s = hdfs_complete(h, tf, client, &e); if (e) ck_abort_msg("exception: %s", hdfs_exception_get_message(e)); ck_assert_msg(s, "complete returned false"); // Open for appending lb = hdfs_append(h, tf, client, &e); if (e) ck_abort_msg("exception: %s", hdfs_exception_get_message(e)); hdfs_object_free(lb); // Cleanup s = hdfs_delete(h, tf, false/*recurse*/, &e); if (e) ck_abort_msg("exception: %s", hdfs_exception_get_message(e)); ck_assert_msg(s, "delete returned false"); }
/** * hdfsOpenFile - Open a file. File handles are not thread-safe. Use your own * synchonrization if you want to share them across threads. * * @param fs The configured filesystem handle. * @param path The full path to the file. * @param flags - OR of O_RDONLY, O_WRONLY (meaning create or overwrite i.e., implies O_TRUNCAT), * O_WRONLY|O_APPEND. Other flags are generally ignored other than (O_RDWR || (O_EXCL & O_CREAT)) * which return NULL and set errno equal ENOTSUP. * @param bufferSize Size of buffer for read/write - pass 0 if you want to use the default values. * @param replication Block replication - pass 0 if you want to use the default values. * @param blocksize Size of block - pass 0 if you want to use the default values. * @return Returns the handle to the open file or NULL on error. */ hdfsFile hdfsOpenFile(hdfsFS fs, const char* path, int flags, int bufferSize, short replication, tSize blocksize) { struct hdfs_object *ex = NULL, *lb = NULL; struct hdfsFile_internal *res; struct hdfsFS_internal *fsclient = fs; enum hdfsFile_mode mode; char *client = NULL, *path_abs; int accmode; union { int64_t num; char bytes[8]; } client_u; const int clientlen = 32; accmode = (flags & O_ACCMODE); if (accmode == O_RDWR) { ERR(ENOTSUP, "Cannot open an hdfs file in O_RDWR mode"); return NULL; } if ((flags & O_CREAT) || (flags & O_EXCL)) WARN("hdfs does not really support O_CREAT and O_EXCL"); if (accmode == O_WRONLY) { if (flags & O_APPEND) mode = FILE_APPEND; else mode = FILE_WRITE; } else { assert(accmode == O_RDONLY); mode = FILE_READ; } path_abs = _makeabs(fs, path); // Defaults if (replication == 0) replication = DEFAULT_REPLICATION; if (blocksize == 0) blocksize = DEFAULT_BLOCK_SIZE; _urandbytes(client_u.bytes, nelem(client_u.bytes)); client = malloc(clientlen); assert(client); snprintf(client, clientlen-1, "DFSClient_%zd", (intmax_t)client_u.num); client[clientlen-1] = '\0'; if (mode == FILE_WRITE) { hdfs_create(fsclient->fs_namenode, path_abs, 0644, client, true/* overwrite */, true/* create parent */, replication, blocksize, &ex); if (ex) { ERR(EINVAL, "Error opening %s for writing: %s", path_abs, hdfs_exception_get_message(ex)); hdfs_object_free(ex); free(client); return NULL; } } else if (mode == FILE_APPEND) { lb = hdfs_append(fsclient->fs_namenode, path_abs, client, &ex); if (ex) { ERR(EINVAL, "Error opening %s for appending: %s", path_abs, hdfs_exception_get_message(ex)); hdfs_object_free(ex); free(client); return NULL; } } res = malloc(sizeof *res); assert(res); res->fi_offset = 0; res->fi_path = strdup(path_abs); assert(res->fi_path); res->fi_mode = mode; res->fi_blocksize = blocksize; res->fi_replication = replication; if (lb && lb->ob_type == H_NULL) { hdfs_object_free(lb); lb = NULL; } res->fi_lastblock = lb; if (mode == FILE_READ) { res->fi_wbuf = NULL; } else { res->fi_wbuf = malloc(blocksize); assert(res->fi_wbuf); } res->fi_wbuf_used = 0; res->fi_client = client; if (lb) hdfs_object_free(lb); if (path_abs != path) free(path_abs); return res; }