ceph/src/client/SyntheticClient.cc
Danny Al-Gaaf 58c732f3e5 client/SyntheticClient.cc: remove dead code
Fix for:

const: At condition do_sync, the value of do_sync must be equal to 0.
dead_error_condition: The condition do_sync cannot be true.
CID 716893 (#1 of 1): Logically dead code (DEADCODE)
dead_error_begin: Execution cannot reach this statement op.OSDOp()

Signed-off-by: Danny Al-Gaaf <danny.al-gaaf@bisect.de>
2014-10-01 17:05:01 +02:00

3512 lines
92 KiB
C++

// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#include <iostream>
#include <sstream>
using namespace std;
#include "common/config.h"
#include "SyntheticClient.h"
#include "osdc/Objecter.h"
#include "osdc/Filer.h"
#include "include/filepath.h"
#include "common/perf_counters.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#include <math.h>
#include <sys/statvfs.h>
#include "common/errno.h"
#include "include/assert.h"
#define dout_subsys ceph_subsys_client
#undef dout_prefix
#define dout_prefix *_dout << "client." << (whoami >= 0 ? whoami:client->get_nodeid()) << " "
// traces
//void trace_include(SyntheticClient *syn, Client *cl, string& prefix);
//void trace_openssh(SyntheticClient *syn, Client *cl, string& prefix);
list<int> syn_modes;
list<int> syn_iargs;
list<string> syn_sargs;
int syn_filer_flags = 0;
void parse_syn_options(vector<const char*>& args)
{
vector<const char*> nargs;
for (unsigned i=0; i<args.size(); i++) {
if (strcmp(args[i],"--syn") == 0) {
++i;
if (strcmp(args[i], "mksnap") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_MKSNAP);
syn_sargs.push_back(args[++i]); // path
syn_sargs.push_back(args[++i]); // name
}
else if (strcmp(args[i], "rmsnap") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_RMSNAP);
syn_sargs.push_back(args[++i]); // path
syn_sargs.push_back(args[++i]); // name
} else if (strcmp(args[i], "mksnapfile") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_MKSNAPFILE);
syn_sargs.push_back(args[++i]); // path
} else if (strcmp(args[i],"rmfile") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_RMFILE );
} else if (strcmp(args[i],"writefile") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_WRITEFILE );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"wrshared") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_WRSHARED );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"writebatch") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_WRITEBATCH );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"readfile") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_READFILE );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"readwriterandom") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_RDWRRANDOM );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"readwriterandom_ex") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_RDWRRANDOM_EX );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"overloadosd0") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_OVERLOAD_OSD_0 );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"readshared") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_READSHARED );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"rw") == 0) {
int a = atoi(args[++i]);
int b = atoi(args[++i]);
syn_modes.push_back( SYNCLIENT_MODE_WRITEFILE );
syn_iargs.push_back( a );
syn_iargs.push_back( b );
syn_modes.push_back( SYNCLIENT_MODE_READFILE );
syn_iargs.push_back( a );
syn_iargs.push_back( b );
} else if (strcmp(args[i],"dumpplacement") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_DUMP );
syn_sargs.push_back( args[++i] );
} else if (strcmp(args[i],"dropcache") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_DROPCACHE );
} else if (strcmp(args[i],"makedirs") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_MAKEDIRS );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"makedirmess") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_MAKEDIRMESS );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"statdirs") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_STATDIRS );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"readdirs") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_READDIRS );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"makefiles") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_MAKEFILES );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"makefiles2") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_MAKEFILES2 );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"linktest") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_LINKTEST );
} else if (strcmp(args[i],"createshared") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_CREATESHARED );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"openshared") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_OPENSHARED );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"createobjects") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_CREATEOBJECTS );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"objectrw") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_OBJECTRW );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"walk") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_FULLWALK );
//syn_sargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"randomwalk") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_RANDOMWALK );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"trace") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_TRACE );
syn_sargs.push_back( args[++i] );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back(1);// data
} else if (strcmp(args[i],"mtrace") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_TRACE );
syn_sargs.push_back( args[++i] );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back(0);// no data
} else if (strcmp(args[i],"thrashlinks") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_THRASHLINKS );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"foo") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_FOO );
} else if (strcmp(args[i],"until") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_UNTIL );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"sleepuntil") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_SLEEPUNTIL );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"only") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_ONLY );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"onlyrange") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_ONLYRANGE );
syn_iargs.push_back( atoi(args[++i]) );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"sleep") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_SLEEP );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"randomsleep") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_RANDOMSLEEP );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"opentest") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_OPENTEST );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"optest") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_OPTEST );
syn_iargs.push_back( atoi(args[++i]) );
} else if (strcmp(args[i],"truncate") == 0) {
syn_modes.push_back( SYNCLIENT_MODE_TRUNCATE );
syn_sargs.push_back(args[++i]);
syn_iargs.push_back(atoi(args[++i]));
} else if (strcmp(args[i],"importfind") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_IMPORTFIND);
syn_sargs.push_back(args[++i]);
syn_sargs.push_back(args[++i]);
syn_iargs.push_back(atoi(args[++i]));
} else if (strcmp(args[i], "lookuphash") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_LOOKUPHASH);
syn_sargs.push_back(args[++i]);
syn_sargs.push_back(args[++i]);
syn_sargs.push_back(args[++i]);
} else if (strcmp(args[i], "lookupino") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_LOOKUPINO);
syn_sargs.push_back(args[++i]);
} else if (strcmp(args[i], "chunkfile") == 0) {
syn_modes.push_back(SYNCLIENT_MODE_CHUNK);
syn_sargs.push_back(args[++i]);
} else {
cerr << "unknown syn arg " << args[i] << std::endl;
assert(0);
}
}
else if (strcmp(args[i], "localize_reads") == 0) {
cerr << "set CEPH_OSD_FLAG_LOCALIZE_READS" << std::endl;
syn_filer_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
}
else {
nargs.push_back(args[i]);
}
}
args = nargs;
}
SyntheticClient::SyntheticClient(Client *client, int w)
{
this->client = client;
whoami = w;
thread_id = 0;
did_readdir = false;
run_only = -1;
exclude = -1;
this->modes = syn_modes;
this->iargs = syn_iargs;
this->sargs = syn_sargs;
run_start = ceph_clock_now(client->cct);
}
#define DBL 2
void *synthetic_client_thread_entry(void *ptr)
{
SyntheticClient *sc = static_cast<SyntheticClient*>(ptr);
//int r =
sc->run();
return 0;//(void*)r;
}
string SyntheticClient::get_sarg(int seq)
{
string a;
if (!sargs.empty()) {
a = sargs.front();
sargs.pop_front();
}
if (a.length() == 0 || a == "~") {
char s[30];
snprintf(s, sizeof(s), "syn.%lld.%d", (long long)client->whoami.v, seq);
a = s;
}
return a;
}
int SyntheticClient::run()
{
dout(15) << "initing" << dendl;
int err = client->init();
if (err < 0) {
dout(0) << "failed to initialize: " << cpp_strerror(err) << dendl;
return -1;
}
dout(15) << "mounting" << dendl;
err = client->mount("");
if (err < 0) {
dout(0) << "failed to mount: " << cpp_strerror(err) << dendl;
client->shutdown();
return -1;
}
//run_start = ceph_clock_now(client->cct);
run_until = utime_t(0,0);
dout(5) << "run" << dendl;
int seq = 0;
for (list<int>::iterator it = modes.begin();
it != modes.end();
++it) {
int mode = *it;
dout(3) << "mode " << mode << dendl;
switch (mode) {
// WHO?
case SYNCLIENT_MODE_ONLY:
{
run_only = iargs.front();
iargs.pop_front();
if (run_only == client->get_nodeid())
dout(2) << "only " << run_only << dendl;
}
break;
case SYNCLIENT_MODE_ONLYRANGE:
{
int first = iargs.front();
iargs.pop_front();
int last = iargs.front();
iargs.pop_front();
if (first <= client->get_nodeid() &&
last > client->get_nodeid()) {
run_only = client->get_nodeid();
dout(2) << "onlyrange [" << first << ", " << last << ") includes me" << dendl;
} else
run_only = client->get_nodeid().v+1; // not me
}
break;
case SYNCLIENT_MODE_EXCLUDE:
{
exclude = iargs.front();
iargs.pop_front();
if (exclude == client->get_nodeid()) {
run_only = client->get_nodeid().v + 1;
dout(2) << "not running " << exclude << dendl;
} else
run_only = -1;
}
break;
// HOW LONG?
case SYNCLIENT_MODE_UNTIL:
{
int iarg1 = iargs.front();
iargs.pop_front();
if (run_me()) {
if (iarg1) {
dout(2) << "until " << iarg1 << dendl;
utime_t dur(iarg1,0);
run_until = run_start + dur;
} else {
dout(2) << "until " << iarg1 << " (no limit)" << dendl;
run_until = utime_t(0,0);
}
}
}
break;
// ...
case SYNCLIENT_MODE_FOO:
if (run_me()) {
foo();
}
did_run_me();
break;
case SYNCLIENT_MODE_RANDOMSLEEP:
{
int iarg1 = iargs.front();
iargs.pop_front();
if (run_me()) {
srand(time(0) + getpid() + client->whoami.v);
sleep(rand() % iarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_SLEEP:
{
int iarg1 = iargs.front();
iargs.pop_front();
if (run_me()) {
dout(2) << "sleep " << iarg1 << dendl;
sleep(iarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_SLEEPUNTIL:
{
int iarg1 = iargs.front();
iargs.pop_front();
if (iarg1 && run_me()) {
dout(2) << "sleepuntil " << iarg1 << dendl;
utime_t at = ceph_clock_now(client->cct) - run_start;
if (at.sec() < iarg1)
sleep(iarg1 - at.sec());
}
did_run_me();
}
break;
case SYNCLIENT_MODE_RANDOMWALK:
{
int iarg1 = iargs.front();
iargs.pop_front();
if (run_me()) {
dout(2) << "randomwalk " << iarg1 << dendl;
random_walk(iarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_DROPCACHE:
{
client->sync_fs();
client->drop_caches();
}
break;
case SYNCLIENT_MODE_DUMP:
{
string sarg1 = get_sarg(0);
if (run_me()) {
dout(2) << "placement dump " << sarg1 << dendl;
dump_placement(sarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_MAKEDIRMESS:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "makedirmess " << sarg1 << " " << iarg1 << dendl;
make_dir_mess(sarg1.c_str(), iarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_MAKEDIRS:
{
string sarg1 = get_sarg(seq++);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
int iarg3 = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "makedirs " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
make_dirs(sarg1.c_str(), iarg1, iarg2, iarg3);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_STATDIRS:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
int iarg3 = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "statdirs " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
stat_dirs(sarg1.c_str(), iarg1, iarg2, iarg3);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_READDIRS:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
int iarg3 = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "readdirs " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
read_dirs(sarg1.c_str(), iarg1, iarg2, iarg3);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_THRASHLINKS:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
int iarg3 = iargs.front(); iargs.pop_front();
int iarg4 = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "thrashlinks " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
thrash_links(sarg1.c_str(), iarg1, iarg2, iarg3, iarg4);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_LINKTEST:
{
if (run_me()) {
link_test();
}
did_run_me();
}
break;
case SYNCLIENT_MODE_MAKEFILES:
{
int num = iargs.front(); iargs.pop_front();
int count = iargs.front(); iargs.pop_front();
int priv = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "makefiles " << num << " " << count << " " << priv << dendl;
make_files(num, count, priv, false);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_MAKEFILES2:
{
int num = iargs.front(); iargs.pop_front();
int count = iargs.front(); iargs.pop_front();
int priv = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "makefiles2 " << num << " " << count << " " << priv << dendl;
make_files(num, count, priv, true);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_CREATESHARED:
{
string sarg1 = get_sarg(0);
int num = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "createshared " << num << dendl;
create_shared(num);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_OPENSHARED:
{
string sarg1 = get_sarg(0);
int num = iargs.front(); iargs.pop_front();
int count = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "openshared " << num << dendl;
open_shared(num, count);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_CREATEOBJECTS:
{
int count = iargs.front(); iargs.pop_front();
int size = iargs.front(); iargs.pop_front();
int inflight = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "createobjects " << cout << " of " << size << " bytes"
<< ", " << inflight << " in flight" << dendl;
create_objects(count, size, inflight);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_OBJECTRW:
{
int count = iargs.front(); iargs.pop_front();
int size = iargs.front(); iargs.pop_front();
int wrpc = iargs.front(); iargs.pop_front();
int overlap = iargs.front(); iargs.pop_front();
int rskew = iargs.front(); iargs.pop_front();
int wskew = iargs.front(); iargs.pop_front();
if (run_me()) {
dout(2) << "objectrw " << cout << " " << size << " " << wrpc
<< " " << overlap << " " << rskew << " " << wskew << dendl;
object_rw(count, size, wrpc, overlap, rskew, wskew);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_FULLWALK:
{
string sarg1;// = get_sarg(0);
if (run_me()) {
dout(2) << "fullwalk" << sarg1 << dendl;
full_walk(sarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_REPEATWALK:
{
string sarg1 = get_sarg(0);
if (run_me()) {
dout(2) << "repeatwalk " << sarg1 << dendl;
while (full_walk(sarg1) == 0) ;
}
did_run_me();
}
break;
case SYNCLIENT_MODE_RMFILE:
{
string sarg1 = get_sarg(0);
if (run_me()) {
rm_file(sarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_WRITEFILE:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
dout(1) << "WRITING SYN CLIENT" << dendl;
if (run_me()) {
write_file(sarg1, iarg1, iarg2);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_CHUNK:
if (run_me()) {
string sarg1 = get_sarg(0);
chunk_file(sarg1);
}
did_run_me();
break;
case SYNCLIENT_MODE_OVERLOAD_OSD_0:
{
dout(1) << "OVERLOADING OSD 0" << dendl;
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
int iarg3 = iargs.front(); iargs.pop_front();
if (run_me()) {
overload_osd_0(iarg1, iarg2, iarg3);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_WRSHARED:
{
string sarg1 = "shared";
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
if (run_me()) {
write_file(sarg1, iarg1, iarg2);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_READSHARED:
{
string sarg1 = "shared";
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
if (run_me()) {
read_file(sarg1, iarg1, iarg2, true);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_WRITEBATCH:
{
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
int iarg3 = iargs.front(); iargs.pop_front();
if (run_me()) {
write_batch(iarg1, iarg2, iarg3);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_READFILE:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
dout(1) << "READING SYN CLIENT" << dendl;
if (run_me()) {
read_file(sarg1, iarg1, iarg2);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_RDWRRANDOM:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
dout(1) << "RANDOM READ WRITE SYN CLIENT" << dendl;
if (run_me()) {
read_random(sarg1, iarg1, iarg2);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_RDWRRANDOM_EX:
{
string sarg1 = get_sarg(0);
int iarg1 = iargs.front(); iargs.pop_front();
int iarg2 = iargs.front(); iargs.pop_front();
dout(1) << "RANDOM READ WRITE SYN CLIENT" << dendl;
if (run_me()) {
read_random_ex(sarg1, iarg1, iarg2);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_TRACE:
{
string tfile = get_sarg(0);
sargs.push_front(string("~"));
int iarg1 = iargs.front(); iargs.pop_front();
int playdata = iargs.front(); iargs.pop_front();
string prefix = get_sarg(0);
char realtfile[100];
snprintf(realtfile, sizeof(realtfile), tfile.c_str(), (int)client->get_nodeid().v);
if (run_me()) {
dout(0) << "trace " << tfile << " prefix=" << prefix << " count=" << iarg1 << " data=" << playdata << dendl;
Trace t(realtfile);
if (iarg1 == 0) iarg1 = 1; // play trace at least once!
for (int i=0; i<iarg1; i++) {
utime_t start = ceph_clock_now(client->cct);
if (time_to_stop()) break;
play_trace(t, prefix, !playdata);
if (time_to_stop()) break;
if (iarg1 > 1) clean_dir(prefix); // clean only if repeat
utime_t lat = ceph_clock_now(client->cct);
lat -= start;
dout(0) << " trace " << tfile << " loop " << (i+1) << "/" << iarg1 << " done in " << (double)lat << " seconds" << dendl;
if (client->logger
&& i > 0
&& i < iarg1-1
) {
//client->logger->finc("trsum", (double)lat);
//client->logger->inc("trnum");
}
}
dout(1) << "done " << dendl;
}
did_run_me();
}
break;
case SYNCLIENT_MODE_OPENTEST:
{
int count = iargs.front(); iargs.pop_front();
if (run_me()) {
for (int i=0; i<count; i++) {
int fd = client->open("test", (rand()%2) ? (O_WRONLY|O_CREAT) : O_RDONLY);
if (fd > 0) client->close(fd);
}
}
did_run_me();
}
break;
case SYNCLIENT_MODE_OPTEST:
{
int count = iargs.front(); iargs.pop_front();
if (run_me()) {
client->mknod("test", 0777);
struct stat st;
for (int i=0; i<count; i++) {
client->lstat("test", &st);
client->chmod("test", 0777);
}
}
did_run_me();
}
break;
case SYNCLIENT_MODE_TRUNCATE:
{
string file = get_sarg(0);
sargs.push_front(file);
int iarg1 = iargs.front(); iargs.pop_front();
if (run_me()) {
client->truncate(file.c_str(), iarg1);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_IMPORTFIND:
{
string base = get_sarg(0);
string find = get_sarg(0);
int data = get_iarg();
if (run_me()) {
import_find(base.c_str(), find.c_str(), data);
}
did_run_me();
}
break;
case SYNCLIENT_MODE_LOOKUPHASH:
{
inodeno_t ino;
string iname = get_sarg(0);
sscanf(iname.c_str(), "%llx", (long long unsigned*)&ino.val);
inodeno_t dirino;
string diname = get_sarg(0);
sscanf(diname.c_str(), "%llx", (long long unsigned*)&dirino.val);
string name = get_sarg(0);
if (run_me()) {
lookup_hash(ino, dirino, name.c_str());
}
}
break;
case SYNCLIENT_MODE_LOOKUPINO:
{
inodeno_t ino;
string iname = get_sarg(0);
sscanf(iname.c_str(), "%llx", (long long unsigned*)&ino.val);
if (run_me()) {
lookup_ino(ino);
}
}
break;
case SYNCLIENT_MODE_MKSNAP:
{
string base = get_sarg(0);
string name = get_sarg(0);
if (run_me())
mksnap(base.c_str(), name.c_str());
did_run_me();
}
break;
case SYNCLIENT_MODE_RMSNAP:
{
string base = get_sarg(0);
string name = get_sarg(0);
if (run_me())
rmsnap(base.c_str(), name.c_str());
did_run_me();
}
break;
case SYNCLIENT_MODE_MKSNAPFILE:
{
string base = get_sarg(0);
if (run_me())
mksnapfile(base.c_str());
did_run_me();
}
break;
default:
assert(0);
}
}
dout(1) << "syn done, unmounting " << dendl;
client->unmount();
client->shutdown();
return 0;
}
int SyntheticClient::start_thread()
{
assert(!thread_id);
pthread_create(&thread_id, NULL, synthetic_client_thread_entry, this);
assert(thread_id);
return 0;
}
int SyntheticClient::join_thread()
{
assert(thread_id);
void *rv;
pthread_join(thread_id, &rv);
return 0;
}
bool roll_die(float p)
{
float r = (float)(rand() % 100000) / 100000.0;
if (r < p)
return true;
else
return false;
}
void SyntheticClient::init_op_dist()
{
op_dist.clear();
#if 0
op_dist.add( CEPH_MDS_OP_STAT, 610 );
op_dist.add( CEPH_MDS_OP_UTIME, 0 );
op_dist.add( CEPH_MDS_OP_CHMOD, 1 );
op_dist.add( CEPH_MDS_OP_CHOWN, 1 );
#endif
op_dist.add( CEPH_MDS_OP_READDIR, 2 );
op_dist.add( CEPH_MDS_OP_MKNOD, 30 );
op_dist.add( CEPH_MDS_OP_LINK, 0 );
op_dist.add( CEPH_MDS_OP_UNLINK, 20 );
op_dist.add( CEPH_MDS_OP_RENAME, 40 );
op_dist.add( CEPH_MDS_OP_MKDIR, 10 );
op_dist.add( CEPH_MDS_OP_RMDIR, 20 );
op_dist.add( CEPH_MDS_OP_SYMLINK, 20 );
op_dist.add( CEPH_MDS_OP_OPEN, 200 );
//op_dist.add( CEPH_MDS_OP_READ, 0 );
//op_dist.add( CEPH_MDS_OP_WRITE, 0 );
//op_dist.add( CEPH_MDS_OP_TRUNCATE, 0 );
//op_dist.add( CEPH_MDS_OP_FSYNC, 0 );
//op_dist.add( CEPH_MDS_OP_RELEASE, 200 );
op_dist.normalize();
}
void SyntheticClient::up()
{
cwd = cwd.prefixpath(cwd.depth()-1);
dout(DBL) << "cd .. -> " << cwd << dendl;
clear_dir();
}
int SyntheticClient::play_trace(Trace& t, string& prefix, bool metadata_only)
{
dout(4) << "play trace prefix '" << prefix << "'" << dendl;
t.start();
char buf[1024];
char buf2[1024];
utime_t start = ceph_clock_now(client->cct);
ceph::unordered_map<int64_t, int64_t> open_files;
ceph::unordered_map<int64_t, dir_result_t*> open_dirs;
ceph::unordered_map<int64_t, Fh*> ll_files;
ceph::unordered_map<int64_t, dir_result_t*> ll_dirs;
ceph::unordered_map<uint64_t, int64_t> ll_inos;
Inode *i1, *i2;
ll_inos[1] = 1; // root inode is known.
// prefix?
const char *p = prefix.c_str();
if (prefix.length()) {
client->mkdir(prefix.c_str(), 0755);
struct stat attr;
i1 = client->ll_get_inode(vinodeno_t(1, CEPH_NOSNAP));
if (client->ll_lookup(i1, prefix.c_str(), &attr, &i2) == 0) {
ll_inos[1] = attr.st_ino;
dout(5) << "'root' ino is " << inodeno_t(attr.st_ino) << dendl;
client->ll_put(i1);
} else {
dout(0) << "warning: play_trace couldn't lookup up my per-client directory" << dendl;
}
} else
(void) client->ll_get_inode(vinodeno_t(1, CEPH_NOSNAP));
utime_t last_status = start;
int n = 0;
// for object traces
Mutex lock("synclient foo");
Cond cond;
bool ack;
bool safe;
C_GatherBuilder safeg(client->cct, new C_SafeCond(&lock, &cond, &safe));
Context *safegref = safeg.new_sub(); // take a ref
while (!t.end()) {
if (++n == 100) {
n = 00;
utime_t now = last_status;
if (now - last_status > 1.0) {
last_status = now;
dout(1) << "play_trace at line " << t.get_line() << dendl;
}
}
if (time_to_stop()) break;
// op
const char *op = t.get_string(buf, 0);
dout(4) << (t.get_line()-1) << ": trace op " << op << dendl;
if (op[0] == '@') {
// timestamp... ignore it!
t.get_int(); // sec
t.get_int(); // usec
op = t.get_string(buf, 0);
}
// high level ops ---------------------
if (strcmp(op, "link") == 0) {
const char *a = t.get_string(buf, p);
const char *b = t.get_string(buf2, p);
client->link(a,b);
} else if (strcmp(op, "unlink") == 0) {
const char *a = t.get_string(buf, p);
client->unlink(a);
} else if (strcmp(op, "rename") == 0) {
const char *a = t.get_string(buf, p);
const char *b = t.get_string(buf2, p);
client->rename(a,b);
} else if (strcmp(op, "mkdir") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
client->mkdir(a, b);
} else if (strcmp(op, "rmdir") == 0) {
const char *a = t.get_string(buf, p);
client->rmdir(a);
} else if (strcmp(op, "symlink") == 0) {
const char *a = t.get_string(buf, p);
const char *b = t.get_string(buf2, p);
client->symlink(a,b);
} else if (strcmp(op, "readlink") == 0) {
const char *a = t.get_string(buf, p);
char buf[100];
client->readlink(a, buf, 100);
} else if (strcmp(op, "lstat") == 0) {
struct stat st;
const char *a = t.get_string(buf, p);
if (strcmp(a, p) != 0 &&
strcmp(a, "/") != 0 &&
strcmp(a, "/lib") != 0 && // or /lib.. that would be a lookup. hack.
a[0] != 0) // stop stating the root directory already
client->lstat(a, &st);
} else if (strcmp(op, "chmod") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
client->chmod(a, b);
} else if (strcmp(op, "chown") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
int64_t c = t.get_int();
client->chown(a, b, c);
} else if (strcmp(op, "utime") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
int64_t c = t.get_int();
struct utimbuf u;
u.actime = b;
u.modtime = c;
client->utime(a, &u);
} else if (strcmp(op, "mknod") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
int64_t c = t.get_int();
client->mknod(a, b, c);
} else if (strcmp(op, "oldmknod") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
client->mknod(a, b, 0);
} else if (strcmp(op, "getdir") == 0) {
const char *a = t.get_string(buf, p);
list<string> contents;
client->getdir(a, contents);
} else if (strcmp(op, "opendir") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
dir_result_t *dirp;
client->opendir(a, &dirp);
if (dirp) open_dirs[b] = dirp;
} else if (strcmp(op, "closedir") == 0) {
int64_t a = t.get_int();
client->closedir(open_dirs[a]);
open_dirs.erase(a);
} else if (strcmp(op, "open") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
int64_t c = t.get_int();
int64_t d = t.get_int();
int64_t fd = client->open(a, b, c);
if (fd > 0) open_files[d] = fd;
} else if (strcmp(op, "oldopen") == 0) {
const char *a = t.get_string(buf, p);
int64_t b = t.get_int();
int64_t d = t.get_int();
int64_t fd = client->open(a, b, 0755);
if (fd > 0) open_files[d] = fd;
} else if (strcmp(op, "close") == 0) {
int64_t id = t.get_int();
int64_t fh = open_files[id];
if (fh > 0) client->close(fh);
open_files.erase(id);
} else if (strcmp(op, "lseek") == 0) {
int64_t f = t.get_int();
int fd = open_files[f];
int64_t off = t.get_int();
int64_t whence = t.get_int();
client->lseek(fd, off, whence);
} else if (strcmp(op, "read") == 0) {
int64_t f = t.get_int();
int64_t size = t.get_int();
int64_t off = t.get_int();
int64_t fd = open_files[f];
if (!metadata_only) {
char *b = new char[size];
client->read(fd, b, size, off);
delete[] b;
}
} else if (strcmp(op, "write") == 0) {
int64_t f = t.get_int();
int64_t fd = open_files[f];
int64_t size = t.get_int();
int64_t off = t.get_int();
if (!metadata_only) {
char *b = new char[size];
memset(b, 1, size); // let's write 1's!
client->write(fd, b, size, off);
delete[] b;
} else {
client->write(fd, NULL, 0, size+off);
}
} else if (strcmp(op, "truncate") == 0) {
const char *a = t.get_string(buf, p);
int64_t l = t.get_int();
client->truncate(a, l);
} else if (strcmp(op, "ftruncate") == 0) {
int64_t f = t.get_int();
int fd = open_files[f];
int64_t l = t.get_int();
client->ftruncate(fd, l);
} else if (strcmp(op, "fsync") == 0) {
int64_t f = t.get_int();
int64_t b = t.get_int();
int fd = open_files[f];
client->fsync(fd, b);
} else if (strcmp(op, "chdir") == 0) {
const char *a = t.get_string(buf, p);
client->chdir(a);
} else if (strcmp(op, "statfs") == 0) {
struct statvfs stbuf;
client->statfs("/", &stbuf);
}
// low level ops ---------------------
else if (strcmp(op, "ll_lookup") == 0) {
int64_t i = t.get_int();
const char *name = t.get_string(buf, p);
int64_t r = t.get_int();
struct stat attr;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_lookup(i1, name, &attr, &i2) == 0)
ll_inos[r] = attr.st_ino;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_forget") == 0) {
int64_t i = t.get_int();
int64_t n = t.get_int();
if (ll_inos.count(i) &&
client->ll_forget(
client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP)), n))
ll_inos.erase(i);
} else if (strcmp(op, "ll_getattr") == 0) {
int64_t i = t.get_int();
struct stat attr;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
client->ll_getattr(i1, &attr);
client->ll_put(i1);
}
} else if (strcmp(op, "ll_setattr") == 0) {
int64_t i = t.get_int();
struct stat attr;
memset(&attr, 0, sizeof(attr));
attr.st_mode = t.get_int();
attr.st_uid = t.get_int();
attr.st_gid = t.get_int();
attr.st_size = t.get_int();
attr.st_mtime = t.get_int();
attr.st_atime = t.get_int();
int mask = t.get_int();
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
client->ll_setattr(i1, &attr, mask);
client->ll_put(i1);
}
} else if (strcmp(op, "ll_readlink") == 0) {
int64_t i = t.get_int();
if (ll_inos.count(i)) {
char buf[PATH_MAX];
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
client->ll_readlink(i1, buf, sizeof(buf));
client->ll_put(i1);
}
} else if (strcmp(op, "ll_mknod") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
int m = t.get_int();
int r = t.get_int();
int64_t ri = t.get_int();
struct stat attr;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_mknod(i1, n, m, r, &attr, &i2) == 0)
ll_inos[ri] = attr.st_ino;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_mkdir") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
int m = t.get_int();
int64_t ri = t.get_int();
struct stat attr;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_mkdir(i1, n, m, &attr, &i2) == 0)
ll_inos[ri] = attr.st_ino;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_symlink") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
const char *v = t.get_string(buf2, p);
int64_t ri = t.get_int();
struct stat attr;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_symlink(i1, n, v, &attr, &i2) == 0)
ll_inos[ri] = attr.st_ino;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_unlink") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
client->ll_unlink(i1, n);
client->ll_put(i1);
}
} else if (strcmp(op, "ll_rmdir") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
client->ll_rmdir(i1, n);
client->ll_put(i1);
}
} else if (strcmp(op, "ll_rename") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
int64_t ni = t.get_int();
const char *nn = t.get_string(buf2, p);
if (ll_inos.count(i) &&
ll_inos.count(ni)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
i2 = client->ll_get_inode(vinodeno_t(ll_inos[ni],CEPH_NOSNAP));
client->ll_rename(i1, n, i2, nn);
client->ll_put(i1);
client->ll_put(i2);
}
} else if (strcmp(op, "ll_link") == 0) {
int64_t i = t.get_int();
int64_t ni = t.get_int();
const char *nn = t.get_string(buf, p);
struct stat attr;
if (ll_inos.count(i) &&
ll_inos.count(ni)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
i2 = client->ll_get_inode(vinodeno_t(ll_inos[ni],CEPH_NOSNAP));
client->ll_link(i1, i2, nn, &attr);
client->ll_put(i1);
client->ll_put(i2);
}
} else if (strcmp(op, "ll_opendir") == 0) {
int64_t i = t.get_int();
int64_t r = t.get_int();
dir_result_t *dirp;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_opendir(i1, &dirp) == 0)
ll_dirs[r] = dirp;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_releasedir") == 0) {
int64_t f = t.get_int();
if (ll_dirs.count(f)) {
client->ll_releasedir(ll_dirs[f]);
ll_dirs.erase(f);
}
} else if (strcmp(op, "ll_open") == 0) {
int64_t i = t.get_int();
int64_t f = t.get_int();
int64_t r = t.get_int();
Fh *fhp;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_open(i1, f, &fhp) == 0)
ll_files[r] = fhp;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_create") == 0) {
int64_t i = t.get_int();
const char *n = t.get_string(buf, p);
int64_t m = t.get_int();
int64_t f = t.get_int();
int64_t r = t.get_int();
int64_t ri = t.get_int();
struct stat attr;
if (ll_inos.count(i)) {
Fh *fhp;
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_create(i1, n, m, f, &attr, NULL, &fhp) == 0) {
ll_inos[ri] = attr.st_ino;
ll_files[r] = fhp;
}
client->ll_put(i1);
}
} else if (strcmp(op, "ll_read") == 0) {
int64_t f = t.get_int();
int64_t off = t.get_int();
int64_t size = t.get_int();
if (ll_files.count(f) &&
!metadata_only) {
bufferlist bl;
client->ll_read(ll_files[f], off, size, &bl);
}
} else if (strcmp(op, "ll_write") == 0) {
int64_t f = t.get_int();
int64_t off = t.get_int();
int64_t size = t.get_int();
if (ll_files.count(f)) {
if (!metadata_only) {
bufferlist bl;
bufferptr bp(size);
bl.push_back(bp);
bp.zero();
client->ll_write(ll_files[f], off, size, bl.c_str());
} else {
client->ll_write(ll_files[f], off+size, 0, NULL);
}
}
} else if (strcmp(op, "ll_flush") == 0) {
int64_t f = t.get_int();
if (!metadata_only &&
ll_files.count(f))
client->ll_flush(ll_files[f]);
} else if (strcmp(op, "ll_fsync") == 0) {
int64_t f = t.get_int();
if (!metadata_only &&
ll_files.count(f))
client->ll_fsync(ll_files[f], false); // FIXME dataonly param
} else if (strcmp(op, "ll_release") == 0) {
int64_t f = t.get_int();
if (ll_files.count(f)) {
client->ll_release(ll_files[f]);
ll_files.erase(f);
}
} else if (strcmp(op, "ll_statfs") == 0) {
int64_t i = t.get_int();
if (ll_inos.count(i))
{} //client->ll_statfs(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
}
// object-level traces
else if (strcmp(op, "o_stat") == 0) {
int64_t oh = t.get_int();
int64_t ol = t.get_int();
object_t oid = file_object_t(oh, ol);
lock.Lock();
object_locator_t oloc(SYNCLIENT_FIRST_POOL);
uint64_t size;
utime_t mtime;
client->objecter->stat(oid, oloc, CEPH_NOSNAP, &size, &mtime, 0, new C_SafeCond(&lock, &cond, &ack));
while (!ack) cond.Wait(lock);
lock.Unlock();
}
else if (strcmp(op, "o_read") == 0) {
int64_t oh = t.get_int();
int64_t ol = t.get_int();
int64_t off = t.get_int();
int64_t len = t.get_int();
object_t oid = file_object_t(oh, ol);
object_locator_t oloc(SYNCLIENT_FIRST_POOL);
lock.Lock();
bufferlist bl;
client->objecter->read(oid, oloc, off, len, CEPH_NOSNAP, &bl, 0, new C_SafeCond(&lock, &cond, &ack));
while (!ack) cond.Wait(lock);
lock.Unlock();
}
else if (strcmp(op, "o_write") == 0) {
int64_t oh = t.get_int();
int64_t ol = t.get_int();
int64_t off = t.get_int();
int64_t len = t.get_int();
object_t oid = file_object_t(oh, ol);
object_locator_t oloc(SYNCLIENT_FIRST_POOL);
lock.Lock();
bufferptr bp(len);
bufferlist bl;
bl.push_back(bp);
SnapContext snapc;
client->objecter->write(oid, oloc, off, len, snapc, bl, ceph_clock_now(client->cct), 0,
new C_SafeCond(&lock, &cond, &ack),
safeg.new_sub());
safeg.activate();
while (!ack) cond.Wait(lock);
lock.Unlock();
}
else if (strcmp(op, "o_zero") == 0) {
int64_t oh = t.get_int();
int64_t ol = t.get_int();
int64_t off = t.get_int();
int64_t len = t.get_int();
object_t oid = file_object_t(oh, ol);
object_locator_t oloc(SYNCLIENT_FIRST_POOL);
lock.Lock();
SnapContext snapc;
client->objecter->zero(oid, oloc, off, len, snapc, ceph_clock_now(client->cct), 0,
new C_SafeCond(&lock, &cond, &ack),
safeg.new_sub());
safeg.activate();
while (!ack) cond.Wait(lock);
lock.Unlock();
}
else {
dout(0) << (t.get_line()-1) << ": *** trace hit unrecognized symbol '" << op << "' " << dendl;
assert(0);
}
}
dout(10) << "trace finished on line " << t.get_line() << dendl;
// wait for safe after an object trace
safegref->complete(0);
lock.Lock();
while (!safe) {
dout(10) << "waiting for safe" << dendl;
cond.Wait(lock);
}
lock.Unlock();
// close open files
for (ceph::unordered_map<int64_t, int64_t>::iterator fi = open_files.begin();
fi != open_files.end();
++fi) {
dout(1) << "leftover close " << fi->second << dendl;
if (fi->second > 0) client->close(fi->second);
}
for (ceph::unordered_map<int64_t, dir_result_t*>::iterator fi = open_dirs.begin();
fi != open_dirs.end();
++fi) {
dout(1) << "leftover closedir " << fi->second << dendl;
if (fi->second != 0) client->closedir(fi->second);
}
for (ceph::unordered_map<int64_t,Fh*>::iterator fi = ll_files.begin();
fi != ll_files.end();
++fi) {
dout(1) << "leftover ll_release " << fi->second << dendl;
if (fi->second) client->ll_release(fi->second);
}
for (ceph::unordered_map<int64_t,dir_result_t*>::iterator fi = ll_dirs.begin();
fi != ll_dirs.end();
++fi) {
dout(1) << "leftover ll_releasedir " << fi->second << dendl;
if (fi->second) client->ll_releasedir(fi->second);
}
return 0;
}
int SyntheticClient::clean_dir(string& basedir)
{
// read dir
list<string> contents;
int r = client->getdir(basedir.c_str(), contents);
if (r < 0) {
dout(1) << "readdir on " << basedir << " returns " << r << dendl;
return r;
}
for (list<string>::iterator it = contents.begin();
it != contents.end();
++it) {
if (*it == ".") continue;
if (*it == "..") continue;
string file = basedir + "/" + *it;
if (time_to_stop()) break;
struct stat st;
int r = client->lstat(file.c_str(), &st);
if (r < 0) {
dout(1) << "stat error on " << file << " r=" << r << dendl;
continue;
}
if ((st.st_mode & S_IFMT) == S_IFDIR) {
clean_dir(file);
client->rmdir(file.c_str());
} else {
client->unlink(file.c_str());
}
}
return 0;
}
int SyntheticClient::full_walk(string& basedir)
{
if (time_to_stop()) return -1;
list<string> dirq;
list<frag_info_t> statq;
dirq.push_back(basedir);
frag_info_t empty;
memset(&empty, 0, sizeof(empty));
statq.push_back(empty);
ceph::unordered_map<inodeno_t, int> nlink;
ceph::unordered_map<inodeno_t, int> nlink_seen;
while (!dirq.empty()) {
string dir = dirq.front();
frag_info_t expect = statq.front();
dirq.pop_front();
statq.pop_front();
frag_info_t actual = empty;
// read dir
list<string> contents;
int r = client->getdir(dir.c_str(), contents);
if (r < 0) {
dout(1) << "readdir on " << dir << " returns " << r << dendl;
continue;
}
for (list<string>::iterator it = contents.begin();
it != contents.end();
++it) {
if (*it == "." ||
*it == "..")
continue;
string file = dir + "/" + *it;
struct stat st;
frag_info_t dirstat;
int r = client->lstat(file.c_str(), &st, &dirstat);
if (r < 0) {
dout(1) << "stat error on " << file << " r=" << r << dendl;
continue;
}
nlink_seen[st.st_ino]++;
nlink[st.st_ino] = st.st_nlink;
if (S_ISDIR(st.st_mode))
actual.nsubdirs++;
else
actual.nfiles++;
// print
char *tm = ctime(&st.st_mtime);
tm[strlen(tm)-1] = 0;
printf("%llx %c%c%c%c%c%c%c%c%c%c %2d %5d %5d %8llu %12s %s\n",
(long long)st.st_ino,
S_ISDIR(st.st_mode) ? 'd':'-',
(st.st_mode & 0400) ? 'r':'-',
(st.st_mode & 0200) ? 'w':'-',
(st.st_mode & 0100) ? 'x':'-',
(st.st_mode & 040) ? 'r':'-',
(st.st_mode & 020) ? 'w':'-',
(st.st_mode & 010) ? 'x':'-',
(st.st_mode & 04) ? 'r':'-',
(st.st_mode & 02) ? 'w':'-',
(st.st_mode & 01) ? 'x':'-',
(int)st.st_nlink,
(int)st.st_uid, (int)st.st_gid,
(long long unsigned)st.st_size,
tm,
file.c_str());
if ((st.st_mode & S_IFMT) == S_IFDIR) {
dirq.push_back(file);
statq.push_back(dirstat);
}
}
if (dir != "" &&
(actual.nsubdirs != expect.nsubdirs ||
actual.nfiles != expect.nfiles)) {
dout(0) << dir << ": expected " << expect << dendl;
dout(0) << dir << ": got " << actual << dendl;
}
}
for (ceph::unordered_map<inodeno_t,int>::iterator p = nlink.begin(); p != nlink.end(); ++p) {
if (nlink_seen[p->first] != p->second)
dout(0) << p->first << " nlink " << p->second << " != " << nlink_seen[p->first] << "seen" << dendl;
}
return 0;
}
int SyntheticClient::dump_placement(string& fn) {
// open file
int fd = client->open(fn.c_str(), O_RDONLY);
dout(5) << "reading from " << fn << " fd " << fd << dendl;
if (fd < 0) return fd;
// How big is it?
struct stat stbuf;
int lstat_result = client->lstat(fn.c_str(), &stbuf);
if (lstat_result < 0) {
dout(0) << "lstat error for file " << fn << dendl;
return lstat_result;
}
off_t filesize = stbuf.st_size;
// grab the placement info
vector<ObjectExtent> extents;
off_t offset = 0;
client->enumerate_layout(fd, extents, filesize, offset);
client->close(fd);
// run through all the object extents
dout(0) << "file size is " << filesize << dendl;
dout(0) << "(osd, start, length) tuples for file " << fn << dendl;
for (vector<ObjectExtent>::iterator i = extents.begin();
i != extents.end(); ++i) {
const OSDMap *osdmap = client->objecter->get_osdmap_read();
int osd = osdmap->get_pg_acting_primary(osdmap->object_locator_to_pg(i->oid, i->oloc));
client->objecter->put_osdmap_read();
// run through all the buffer extents
for (vector<pair<uint64_t, uint64_t> >::iterator j = i->buffer_extents.begin();
j != i->buffer_extents.end(); ++j) {
dout(0) << "OSD " << osd << ", offset " << (*j).first
<< ", length " << (*j).second << dendl;
}
}
return 0;
}
int SyntheticClient::make_dirs(const char *basedir, int dirs, int files, int depth)
{
if (time_to_stop()) return 0;
// make sure base dir exists
int r = client->mkdir(basedir, 0755);
if (r != 0) {
dout(1) << "can't make base dir? " << basedir << dendl;
//return -1;
}
// children
char d[500];
dout(3) << "make_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
for (int i=0; i<files; i++) {
snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
client->mknod(d, 0644);
}
if (depth == 0) return 0;
for (int i=0; i<dirs; i++) {
snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
make_dirs(d, dirs, files, depth-1);
}
return 0;
}
int SyntheticClient::stat_dirs(const char *basedir, int dirs, int files, int depth)
{
if (time_to_stop()) return 0;
// make sure base dir exists
struct stat st;
int r = client->lstat(basedir, &st);
if (r != 0) {
dout(1) << "can't make base dir? " << basedir << dendl;
return -1;
}
// children
char d[500];
dout(3) << "stat_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
for (int i=0; i<files; i++) {
snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
client->lstat(d, &st);
}
if (depth == 0) return 0;
for (int i=0; i<dirs; i++) {
snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
stat_dirs(d, dirs, files, depth-1);
}
return 0;
}
int SyntheticClient::read_dirs(const char *basedir, int dirs, int files, int depth)
{
if (time_to_stop()) return 0;
struct stat st;
// children
char d[500];
dout(3) << "read_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
list<string> contents;
utime_t s = ceph_clock_now(client->cct);
int r = client->getdir(basedir, contents);
utime_t e = ceph_clock_now(client->cct);
e -= s;
if (r < 0) {
dout(0) << "read_dirs couldn't readdir " << basedir << ", stopping" << dendl;
return -1;
}
for (int i=0; i<files; i++) {
snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
utime_t s = ceph_clock_now(client->cct);
if (client->lstat(d, &st) < 0) {
dout(2) << "read_dirs failed stat on " << d << ", stopping" << dendl;
return -1;
}
utime_t e = ceph_clock_now(client->cct);
e -= s;
}
if (depth > 0)
for (int i=0; i<dirs; i++) {
snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
if (read_dirs(d, dirs, files, depth-1) < 0) return -1;
}
return 0;
}
int SyntheticClient::make_files(int num, int count, int priv, bool more)
{
int whoami = client->get_nodeid().v;
char d[255];
if (priv) {
for (int c=0; c<count; c++) {
snprintf(d, sizeof(d), "dir.%d.run%d", whoami, c);
client->mkdir(d, 0755);
}
} else {
// shared
if (true || whoami == 0) {
for (int c=0; c<count; c++) {
snprintf(d, sizeof(d), "dir.%d.run%d", 0, c);
client->mkdir(d, 0755);
}
} else {
sleep(2);
}
}
// files
struct stat st;
utime_t start = ceph_clock_now(client->cct);
for (int c=0; c<count; c++) {
for (int n=0; n<num; n++) {
snprintf(d, sizeof(d), "dir.%d.run%d/file.client%d.%d", priv ? whoami:0, c, whoami, n);
client->mknod(d, 0644);
if (more) {
client->lstat(d, &st);
int fd = client->open(d, O_RDONLY);
client->unlink(d);
client->close(fd);
}
if (time_to_stop()) return 0;
}
}
utime_t end = ceph_clock_now(client->cct);
end -= start;
dout(0) << "makefiles time is " << end << " or " << ((double)end / (double)num) <<" per file" << dendl;
return 0;
}
int SyntheticClient::link_test()
{
char d[255];
char e[255];
// create files
int num = 200;
client->mkdir("orig", 0755);
client->mkdir("copy", 0755);
utime_t start = ceph_clock_now(client->cct);
for (int i=0; i<num; i++) {
snprintf(d, sizeof(d), "orig/file.%d", i);
client->mknod(d, 0755);
}
utime_t end = ceph_clock_now(client->cct);
end -= start;
dout(0) << "orig " << end << dendl;
// link
start = ceph_clock_now(client->cct);
for (int i=0; i<num; i++) {
snprintf(d, sizeof(d), "orig/file.%d", i);
snprintf(e, sizeof(e), "copy/file.%d", i);
client->link(d, e);
}
end = ceph_clock_now(client->cct);
end -= start;
dout(0) << "copy " << end << dendl;
return 0;
}
int SyntheticClient::create_shared(int num)
{
// files
char d[255];
client->mkdir("test", 0755);
for (int n=0; n<num; n++) {
snprintf(d, sizeof(d), "test/file.%d", n);
client->mknod(d, 0644);
}
return 0;
}
int SyntheticClient::open_shared(int num, int count)
{
// files
char d[255];
for (int c=0; c<count; c++) {
// open
list<int> fds;
for (int n=0; n<num; n++) {
snprintf(d, sizeof(d), "test/file.%d", n);
int fd = client->open(d,O_RDONLY);
if (fd > 0) fds.push_back(fd);
}
if (false && client->get_nodeid() == 0)
for (int n=0; n<num; n++) {
snprintf(d, sizeof(d), "test/file.%d", n);
client->unlink(d);
}
while (!fds.empty()) {
int fd = fds.front();
fds.pop_front();
client->close(fd);
}
}
return 0;
}
// Hits OSD 0 with writes to various files with OSD 0 as the primary.
int SyntheticClient::overload_osd_0(int n, int size, int wrsize) {
// collect a bunch of files starting on OSD 0
int left = n;
int tried = 0;
while (left < 0) {
// pull open a file
dout(0) << "in OSD overload" << dendl;
string filename = get_sarg(tried);
dout(1) << "OSD Overload workload: trying file " << filename << dendl;
int fd = client->open(filename.c_str(), O_RDWR|O_CREAT);
++tried;
// only use the file if its first primary is OSD 0
int primary_osd = check_first_primary(fd);
if (primary_osd != 0) {
client->close(fd);
dout(1) << "OSD Overload workload: SKIPPING file " << filename <<
" with OSD " << primary_osd << " as first primary. " << dendl;
continue;
}
dout(1) << "OSD Overload workload: USING file " << filename <<
" with OSD 0 as first primary. " << dendl;
--left;
// do whatever operation we want to do on the file. How about a write?
write_fd(fd, size, wrsize);
}
return 0;
}
// See what the primary is for the first object in this file.
int SyntheticClient::check_first_primary(int fh)
{
vector<ObjectExtent> extents;
client->enumerate_layout(fh, extents, 1, 0);
const OSDMap *osdmap = client->objecter->get_osdmap_read();
int primary = osdmap->get_pg_acting_primary(osdmap->object_locator_to_pg(extents.begin()->oid,
extents.begin()->oloc));
client->objecter->put_osdmap_read();
return primary;
}
int SyntheticClient::rm_file(string& fn)
{
return client->unlink(fn.c_str());
}
int SyntheticClient::write_file(string& fn, int size, loff_t wrsize) // size is in MB, wrsize in bytes
{
//uint64_t wrsize = 1024*256;
char *buf = new char[wrsize+100]; // 1 MB
memset(buf, 7, wrsize);
int64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)wrsize;
int fd = client->open(fn.c_str(), O_RDWR|O_CREAT);
dout(5) << "writing to " << fn << " fd " << fd << dendl;
if (fd < 0) {
delete[] buf;
return fd;
}
utime_t from = ceph_clock_now(client->cct);
utime_t start = from;
uint64_t bytes = 0, total = 0;
for (loff_t i=0; i<chunks; i++) {
if (time_to_stop()) {
dout(0) << "stopping" << dendl;
break;
}
dout(2) << "writing block " << i << "/" << chunks << dendl;
// fill buf with a 16 byte fingerprint
// 64 bits : file offset
// 64 bits : client id
// = 128 bits (16 bytes)
uint64_t *p = (uint64_t*)buf;
while ((char*)p < buf + wrsize) {
*p = (uint64_t)i*(uint64_t)wrsize + (uint64_t)((char*)p - buf);
p++;
*p = client->get_nodeid().v;
p++;
}
client->write(fd, buf, wrsize, i*wrsize);
bytes += wrsize;
total += wrsize;
utime_t now = ceph_clock_now(client->cct);
if (now - from >= 1.0) {
double el = now - from;
dout(0) << "write " << (bytes / el / 1048576.0) << " MB/sec" << dendl;
from = now;
bytes = 0;
}
}
client->fsync(fd, true);
utime_t stop = ceph_clock_now(client->cct);
double el = stop - start;
dout(0) << "write total " << (total / el / 1048576.0) << " MB/sec ("
<< total << " bytes in " << el << " seconds)" << dendl;
client->close(fd);
delete[] buf;
return 0;
}
int SyntheticClient::write_fd(int fd, int size, int wrsize) // size is in MB, wrsize in bytes
{
//uint64_t wrsize = 1024*256;
char *buf = new char[wrsize+100]; // 1 MB
memset(buf, 7, wrsize);
uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)wrsize;
//dout(5) << "SyntheticClient::write_fd: writing to fd " << fd << dendl;
if (fd < 0) {
delete[] buf;
return fd;
}
for (unsigned i=0; i<chunks; i++) {
if (time_to_stop()) {
dout(0) << "stopping" << dendl;
break;
}
dout(2) << "writing block " << i << "/" << chunks << dendl;
// fill buf with a 16 byte fingerprint
// 64 bits : file offset
// 64 bits : client id
// = 128 bits (16 bytes)
uint64_t *p = (uint64_t*)buf;
while ((char*)p < buf + wrsize) {
*p = (uint64_t)i*(uint64_t)wrsize + (uint64_t)((char*)p - buf);
p++;
*p = client->get_nodeid().v;
p++;
}
client->write(fd, buf, wrsize, i*wrsize);
}
client->close(fd);
delete[] buf;
return 0;
}
int SyntheticClient::write_batch(int nfile, int size, int wrsize)
{
for (int i=0; i<nfile; i++) {
string sarg1 = get_sarg(i);
dout(0) << "Write file " << sarg1 << dendl;
write_file(sarg1, size, wrsize);
}
return 0;
}
// size is in MB, wrsize in bytes
int SyntheticClient::read_file(const std::string& fn, int size,
int rdsize, bool ignoreprint)
{
char *buf = new char[rdsize];
memset(buf, 1, rdsize);
uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
int fd = client->open(fn.c_str(), O_RDONLY);
dout(5) << "reading from " << fn << " fd " << fd << dendl;
if (fd < 0) {
delete[] buf;
return fd;
}
utime_t from = ceph_clock_now(client->cct);
utime_t start = from;
uint64_t bytes = 0, total = 0;
for (unsigned i=0; i<chunks; i++) {
if (time_to_stop()) break;
dout(2) << "reading block " << i << "/" << chunks << dendl;
int r = client->read(fd, buf, rdsize, i*rdsize);
if (r < rdsize) {
dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
break;
}
bytes += rdsize;
total += rdsize;
utime_t now = ceph_clock_now(client->cct);
if (now - from >= 1.0) {
double el = now - from;
dout(0) << "read " << (bytes / el / 1048576.0) << " MB/sec" << dendl;
from = now;
bytes = 0;
}
// verify fingerprint
int bad = 0;
uint64_t *p = (uint64_t*)buf;
uint64_t readoff;
int64_t readclient;
while ((char*)p + 32 < buf + rdsize) {
readoff = *p;
uint64_t wantoff = (uint64_t)i*(uint64_t)rdsize + (uint64_t)((char*)p - buf);
p++;
readclient = *p;
p++;
if (readoff != wantoff ||
readclient != client->get_nodeid()) {
if (!bad && !ignoreprint)
dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
<< ", should be offset " << wantoff << " clietn " << client->get_nodeid()
<< dendl;
bad++;
}
}
if (bad && !ignoreprint)
dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
}
utime_t stop = ceph_clock_now(client->cct);
double el = stop - start;
dout(0) << "read total " << (total / el / 1048576.0) << " MB/sec ("
<< total << " bytes in " << el << " seconds)" << dendl;
client->close(fd);
delete[] buf;
return 0;
}
class C_Ref : public Context {
Mutex& lock;
Cond& cond;
int *ref;
public:
C_Ref(Mutex &l, Cond &c, int *r) : lock(l), cond(c), ref(r) {
lock.Lock();
(*ref)++;
lock.Unlock();
}
void finish(int) {
lock.Lock();
(*ref)--;
cond.Signal();
lock.Unlock();
}
};
int SyntheticClient::create_objects(int nobj, int osize, int inflight)
{
// divy up
int numc = client->cct->_conf->num_client ? client->cct->_conf->num_client : 1;
int start, inc, end;
if (1) {
// strided
start = client->get_nodeid().v; //nobjs % numc;
inc = numc;
end = start + nobj;
} else {
// segments
start = nobj * client->get_nodeid().v / numc;
inc = 1;
end = nobj * (client->get_nodeid().v+1) / numc;
}
dout(5) << "create_objects " << nobj << " size=" << osize
<< " .. doing [" << start << "," << end << ") inc " << inc
<< dendl;
bufferptr bp(osize);
bp.zero();
bufferlist bl;
bl.push_back(bp);
Mutex lock("create_objects lock");
Cond cond;
int unack = 0;
int unsafe = 0;
list<utime_t> starts;
for (int i=start; i<end; i += inc) {
if (time_to_stop()) break;
object_t oid = file_object_t(999, i);
object_locator_t oloc(SYNCLIENT_FIRST_POOL);
SnapContext snapc;
if (i % inflight == 0) {
dout(6) << "create_objects " << i << "/" << (nobj+1) << dendl;
}
dout(10) << "writing " << oid << dendl;
starts.push_back(ceph_clock_now(client->cct));
client->client_lock.Lock();
client->objecter->write(oid, oloc, 0, osize, snapc, bl, ceph_clock_now(client->cct), 0,
new C_Ref(lock, cond, &unack),
new C_Ref(lock, cond, &unsafe));
client->client_lock.Unlock();
lock.Lock();
while (unack > inflight) {
dout(20) << "waiting for " << unack << " unack" << dendl;
cond.Wait(lock);
}
lock.Unlock();
utime_t lat = ceph_clock_now(client->cct);
lat -= starts.front();
starts.pop_front();
}
lock.Lock();
while (unack > 0) {
dout(20) << "waiting for " << unack << " unack" << dendl;
cond.Wait(lock);
}
while (unsafe > 0) {
dout(10) << "waiting for " << unsafe << " unsafe" << dendl;
cond.Wait(lock);
}
lock.Unlock();
dout(5) << "create_objects done" << dendl;
return 0;
}
int SyntheticClient::object_rw(int nobj, int osize, int wrpc,
int overlappc,
double rskew, double wskew)
{
dout(5) << "object_rw " << nobj << " size=" << osize << " with "
<< wrpc << "% writes"
<< ", " << overlappc << "% overlap"
<< ", rskew = " << rskew
<< ", wskew = " << wskew
<< dendl;
bufferptr bp(osize);
bp.zero();
bufferlist bl;
bl.push_back(bp);
// start with odd number > nobj
rjhash<uint32_t> h;
unsigned prime = nobj + 1; // this is the minimum!
prime += h(nobj) % (3*nobj); // bump it up some
prime |= 1; // make it odd
while (true) {
unsigned j;
for (j=2; j*j<=prime; j++)
if (prime % j == 0) break;
if (j*j > prime) {
break;
//cout << "prime " << prime << endl;
}
prime += 2;
}
Mutex lock("lock");
Cond cond;
int unack = 0;
while (1) {
if (time_to_stop()) break;
// read or write?
bool write = (rand() % 100) < wrpc;
// choose object
double r = drand48(); // [0..1)
long o;
if (write) {
o = (long)trunc(pow(r, wskew) * (double)nobj); // exponentially skew towards 0
int pnoremap = (long)(r * 100.0);
if (pnoremap >= overlappc)
o = (o*prime) % nobj; // remap
} else {
o = (long)trunc(pow(r, rskew) * (double)nobj); // exponentially skew towards 0
}
object_t oid = file_object_t(999, o);
object_locator_t oloc(SYNCLIENT_FIRST_POOL);
SnapContext snapc;
client->client_lock.Lock();
utime_t start = ceph_clock_now(client->cct);
if (write) {
dout(10) << "write to " << oid << dendl;
ObjectOperation m;
OSDOp op;
op.op.op = CEPH_OSD_OP_WRITE;
op.op.extent.offset = 0;
op.op.extent.length = osize;
op.indata = bl;
m.ops.push_back(op);
client->objecter->mutate(oid, oloc, m, snapc, ceph_clock_now(client->cct), 0,
NULL, new C_Ref(lock, cond, &unack));
} else {
dout(10) << "read from " << oid << dendl;
bufferlist inbl;
client->objecter->read(oid, oloc, 0, osize, CEPH_NOSNAP, &inbl, 0,
new C_Ref(lock, cond, &unack));
}
client->client_lock.Unlock();
lock.Lock();
while (unack > 0) {
dout(20) << "waiting for " << unack << " unack" << dendl;
cond.Wait(lock);
}
lock.Unlock();
utime_t lat = ceph_clock_now(client->cct);
lat -= start;
if (client->logger) {
if (write)
client->logger->tset(l_c_owrlat, lat);
else
client->logger->tset(l_c_ordlat, lat);
}
}
return 0;
}
int SyntheticClient::read_random(string& fn, int size, int rdsize) // size is in MB, wrsize in bytes
{
__uint64_t chunks = (__uint64_t)size * (__uint64_t)(1024*1024) / (__uint64_t)rdsize;
int fd = client->open(fn.c_str(), O_RDWR);
dout(5) << "reading from " << fn << " fd " << fd << dendl;
// dout(0) << "READING FROM " << fn << " fd " << fd << dendl;
// dout(0) << "filename " << fn << " size:" << size << " read size|" << rdsize << "|" << "\ chunks: |" << chunks <<"|" << dendl;
if (fd < 0) return fd;
int offset = 0;
char * buf = NULL;
for (unsigned i=0; i<2000; i++) {
if (time_to_stop()) break;
bool read=false;
time_t seconds;
time( &seconds);
srand(seconds);
// use rand instead ??
double x = drand48();
//dout(0) << "RANDOM NUMBER RETURN |" << x << "|" << dendl;
// cleanup before call 'new'
if (buf != NULL) {
delete[] buf;
buf = NULL;
}
if ( x < 0.5)
{
//dout(0) << "DECIDED TO READ " << x << dendl;
buf = new char[rdsize];
memset(buf, 1, rdsize);
read=true;
}
else
{
// dout(0) << "DECIDED TO WRITE " << x << dendl;
buf = new char[rdsize+100]; // 1 MB
memset(buf, 7, rdsize);
}
//double y = drand48() ;
//dout(0) << "OFFSET is |" << offset << "| chunks |" << chunks<< dendl;
if ( read)
{
offset=(rand())%(chunks+1);
dout(2) << "reading block " << offset << "/" << chunks << dendl;
int r = client->read(fd, buf, rdsize,
offset*rdsize);
if (r < rdsize) {
dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
}
}
else
{
dout(2) << "writing block " << offset << "/" << chunks << dendl;
// fill buf with a 16 byte fingerprint
// 64 bits : file offset
// 64 bits : client id
// = 128 bits (16 bytes)
//if (true )
//{
//int count = rand()%10;
//for ( int j=0;j<count; j++ )
//{
offset=(rand())%(chunks+1);
__uint64_t *p = (__uint64_t*)buf;
while ((char*)p < buf + rdsize) {
*p = offset*rdsize + (char*)p - buf;
p++;
*p = client->get_nodeid().v;
p++;
}
client->write(fd, buf, rdsize,
offset*rdsize);
//}
//}
}
// verify fingerprint
if ( read )
{
int bad = 0;
__int64_t *p = (__int64_t*)buf;
__int64_t readoff, readclient;
while ((char*)p + 32 < buf + rdsize) {
readoff = *p;
__int64_t wantoff = offset*rdsize + (__int64_t)((char*)p - buf);
p++;
readclient = *p;
p++;
if (readoff != wantoff ||
readclient != client->get_nodeid()) {
if (!bad)
dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
<< ", should be offset " << wantoff << " clietn " << client->get_nodeid()
<< dendl;
bad++;
}
}
if (bad)
dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
}
}
client->close(fd);
delete[] buf;
return 0;
}
//#include<stdio.h>
//#include<stdlib.h>
int normdist(int min, int max, int stdev) /* specifies input values */;
//main()
//{
// for ( int i=0; i < 10; i++ )
// normdist ( 0 , 10, 1 );
//}
int normdist(int min, int max, int stdev) /* specifies input values */
{
/* min: Minimum value; max: Maximum value; stdev: degree of deviation */
//int min, max, stdev; {
time_t seconds;
time( &seconds);
srand(seconds);
int range, iterate, result;
/* declare range, iterate and result as integers, to avoid the need for
floating point math*/
result = 0;
/* ensure result is initialized to 0 */
range = max -min;
/* calculate range of possible values between the max and min values */
iterate = range / stdev;
/* this number of iterations ensures the proper shape of the resulting
curve */
stdev += 1; /* compensation for integer vs. floating point math */
for (int c = iterate; c != 0; c--) /* loop through iterations */
{
// result += (uniform (1, 100) * stdev) / 100; /* calculate and
result += ( (rand()%100 + 1) * stdev) / 100;
// printf("result=%d\n", result );
}
printf("\n final result=%d\n", result );
return result + min; /* send final result back */
}
int SyntheticClient::read_random_ex(string& fn, int size, int rdsize) // size is in MB, wrsize in bytes
{
__uint64_t chunks = (__uint64_t)size * (__uint64_t)(1024*1024) / (__uint64_t)rdsize;
int fd = client->open(fn.c_str(), O_RDWR);
dout(5) << "reading from " << fn << " fd " << fd << dendl;
// dout(0) << "READING FROM " << fn << " fd " << fd << dendl;
// dout(0) << "filename " << fn << " size:" << size << " read size|" << rdsize << "|" << "\ chunks: |" << chunks <<"|" << dendl;
if (fd < 0) return fd;
int offset = 0;
char * buf = NULL;
for (unsigned i=0; i<2000; i++) {
if (time_to_stop()) break;
bool read=false;
time_t seconds;
time( &seconds);
srand(seconds);
// use rand instead ??
double x = drand48();
//dout(0) << "RANDOM NUMBER RETURN |" << x << "|" << dendl;
// cleanup before call 'new'
if (buf != NULL) {
delete[] buf;
buf = NULL;
}
if ( x < 0.5)
{
//dout(0) << "DECIDED TO READ " << x << dendl;
buf = new char[rdsize];
memset(buf, 1, rdsize);
read=true;
}
else
{
// dout(0) << "DECIDED TO WRITE " << x << dendl;
buf = new char[rdsize+100]; // 1 MB
memset(buf, 7, rdsize);
}
//double y = drand48() ;
//dout(0) << "OFFSET is |" << offset << "| chunks |" << chunks<< dendl;
if ( read)
{
//offset=(rand())%(chunks+1);
/* if ( chunks > 10000 )
offset= normdist( 0 , chunks/1000 , 5 )*1000;
else if ( chunks > 1000 )
offset= normdist( 0 , chunks/100 , 5 )*100;
else if ( chunks > 100 )
offset= normdist( 0 , chunks/20 , 5 )*20;*/
dout(2) << "reading block " << offset << "/" << chunks << dendl;
int r = client->read(fd, buf, rdsize,
offset*rdsize);
if (r < rdsize) {
dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
}
}
else
{
dout(2) << "writing block " << offset << "/" << chunks << dendl;
// fill buf with a 16 byte fingerprint
// 64 bits : file offset
// 64 bits : client id
// = 128 bits (16 bytes)
//if (true )
//{
int count = rand()%10;
for ( int j=0;j<count; j++ )
{
offset=(rand())%(chunks+1);
__uint64_t *p = (__uint64_t*)buf;
while ((char*)p < buf + rdsize) {
*p = offset*rdsize + (char*)p - buf;
p++;
*p = client->get_nodeid().v;
p++;
}
client->write(fd, buf, rdsize,
offset*rdsize);
}
//}
}
// verify fingerprint
if ( read )
{
int bad = 0;
__int64_t *p = (__int64_t*)buf;
__int64_t readoff, readclient;
while ((char*)p + 32 < buf + rdsize) {
readoff = *p;
__int64_t wantoff = offset*rdsize + (__int64_t)((char*)p - buf);
p++;
readclient = *p;
p++;
if (readoff != wantoff ||
readclient != client->get_nodeid()) {
if (!bad)
dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
<< ", should be offset " << wantoff << " clietn " << client->get_nodeid()
<< dendl;
bad++;
}
}
if (bad)
dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
}
}
client->close(fd);
delete[] buf;
return 0;
}
int SyntheticClient::random_walk(int num_req)
{
int left = num_req;
//dout(1) << "random_walk() will do " << left << " ops" << dendl;
init_op_dist(); // set up metadata op distribution
while (left > 0) {
left--;
if (time_to_stop()) break;
// ascend?
if (cwd.depth() && !roll_die(::pow((double).9, (double)cwd.depth()))) {
dout(DBL) << "die says up" << dendl;
up();
continue;
}
// descend?
if (.9*roll_die(::pow((double).9,(double)cwd.depth())) && !subdirs.empty()) {
string s = get_random_subdir();
cwd.push_dentry( s );
dout(DBL) << "cd " << s << " -> " << cwd << dendl;
clear_dir();
continue;
}
int op = 0;
filepath path;
if (contents.empty() && roll_die(.3)) {
if (did_readdir) {
dout(DBL) << "empty dir, up" << dendl;
up();
} else
op = CEPH_MDS_OP_READDIR;
} else {
op = op_dist.sample();
}
//dout(DBL) << "op is " << op << dendl;
int r = 0;
// do op
if (op == CEPH_MDS_OP_UNLINK) {
if (contents.empty())
op = CEPH_MDS_OP_READDIR;
else
r = client->unlink( get_random_sub() ); // will fail on dirs
}
if (op == CEPH_MDS_OP_RENAME) {
if (contents.empty())
op = CEPH_MDS_OP_READDIR;
else {
r = client->rename( get_random_sub(), make_sub("ren") );
}
}
if (op == CEPH_MDS_OP_MKDIR) {
r = client->mkdir( make_sub("mkdir"), 0755);
}
if (op == CEPH_MDS_OP_RMDIR) {
if (!subdirs.empty())
r = client->rmdir( get_random_subdir() );
else
r = client->rmdir( cwd.c_str() ); // will pbly fail
}
if (op == CEPH_MDS_OP_SYMLINK) {
}
/*
if (op == CEPH_MDS_OP_CHMOD) {
if (contents.empty())
op = CEPH_MDS_OP_READDIR;
else
r = client->chmod( get_random_sub(), rand() & 0755 );
}
if (op == CEPH_MDS_OP_CHOWN) {
if (contents.empty()) r = client->chown( cwd.c_str(), rand(), rand() );
else
r = client->chown( get_random_sub(), rand(), rand() );
}
if (op == CEPH_MDS_OP_UTIME) {
struct utimbuf b;
memset(&b, 1, sizeof(b));
if (contents.empty())
r = client->utime( cwd.c_str(), &b );
else
r = client->utime( get_random_sub(), &b );
}
*/
if (op == CEPH_MDS_OP_LINK) {
}
if (op == CEPH_MDS_OP_MKNOD) {
r = client->mknod( make_sub("mknod"), 0644);
}
if (op == CEPH_MDS_OP_OPEN) {
if (contents.empty())
op = CEPH_MDS_OP_READDIR;
else {
r = client->open( get_random_sub(), O_RDONLY );
if (r > 0) {
assert(open_files.count(r) == 0);
open_files.insert(r);
}
}
}
/*if (op == CEPH_MDS_OP_RELEASE) { // actually, close
if (open_files.empty())
op = CEPH_MDS_OP_STAT;
else {
int fh = get_random_fh();
r = client->close( fh );
if (r == 0) open_files.erase(fh);
}
}
*/
if (op == CEPH_MDS_OP_GETATTR) {
struct stat st;
if (contents.empty()) {
if (did_readdir) {
if (roll_die(.1)) {
dout(DBL) << "stat in empty dir, up" << dendl;
up();
} else {
op = CEPH_MDS_OP_MKNOD;
}
} else
op = CEPH_MDS_OP_READDIR;
} else
r = client->lstat(get_random_sub(), &st);
}
if (op == CEPH_MDS_OP_READDIR) {
clear_dir();
list<string> c;
r = client->getdir( cwd.c_str(), c );
for (list<string>::iterator it = c.begin();
it != c.end();
++it) {
//dout(DBL) << " got " << *it << dendl;
assert(0);
/*contents[*it] = it->second;
if (it->second &&
S_ISDIR(it->second->st_mode))
subdirs.insert(*it);
*/
}
did_readdir = true;
}
// errors?
if (r < 0) {
// reevaluate cwd.
//while (cwd.depth()) {
//if (client->lookup(cwd)) break; // it's in the cache
//dout(DBL) << "r = " << r << ", client doesn't have " << cwd << ", cd .." << dendl;
dout(DBL) << "r = " << r << ", client may not have " << cwd << ", cd .." << dendl;
up();
//}
}
}
// close files
dout(DBL) << "closing files" << dendl;
while (!open_files.empty()) {
int fh = get_random_fh();
int r = client->close( fh );
if (r == 0) open_files.erase(fh);
}
dout(DBL) << "done" << dendl;
return 0;
}
void SyntheticClient::make_dir_mess(const char *basedir, int n)
{
vector<string> dirs;
dirs.push_back(basedir);
dirs.push_back(basedir);
client->mkdir(basedir, 0755);
// motivation:
// P(dir) ~ subdirs_of(dir) + 2
// from 5-year metadata workload paper in fast'07
// create dirs
for (int i=0; i<n; i++) {
// pick a dir
int k = rand() % dirs.size();
string parent = dirs[k];
// pick a name
std::stringstream ss;
ss << parent << "/" << i;
string dir = ss.str();
// update dirs
dirs.push_back(parent);
dirs.push_back(dir);
dirs.push_back(dir);
// do it
client->mkdir(dir.c_str(), 0755);
}
}
void SyntheticClient::foo()
{
if (1) {
// make 2 parallel dirs, link/unlink between them.
char a[100], b[100];
client->mkdir("/a", 0755);
client->mkdir("/b", 0755);
for (int i=0; i<10; i++) {
snprintf(a, sizeof(a), "/a/%d", i);
client->mknod(a, 0644);
}
while (1) {
for (int i=0; i<10; i++) {
snprintf(a, sizeof(a), "/a/%d", i);
snprintf(b, sizeof(b), "/b/%d", i);
client->link(a, b);
}
for (int i=0; i<10; i++) {
snprintf(b, sizeof(b), "/b/%d", i);
client->unlink(b);
}
}
return;
}
if (1) {
// bug1.cpp
const char *fn = "blah";
char buffer[8192];
client->unlink(fn);
int handle = client->open(fn,O_CREAT|O_RDWR,S_IRWXU);
assert(handle>=0);
int r=client->write(handle,buffer,8192);
assert(r>=0);
r=client->close(handle);
assert(r>=0);
handle = client->open(fn,O_RDWR); // open the same file, it must have some data already
assert(handle>=0);
r=client->read(handle,buffer,8192);
assert(r==8192); // THIS ASSERTION FAILS with disabled cache
r=client->close(handle);
assert(r>=0);
return;
}
if (1) {
dout(0) << "first" << dendl;
int fd = client->open("tester", O_WRONLY|O_CREAT);
client->write(fd, "hi there", 0, 8);
client->close(fd);
dout(0) << "sleep" << dendl;
sleep(10);
dout(0) << "again" << dendl;
fd = client->open("tester", O_WRONLY|O_CREAT);
client->write(fd, "hi there", 0, 8);
client->close(fd);
return;
}
if (1) {
// open some files
srand(0);
for (int i=0; i<20; i++) {
int s = 5;
int a = rand() % s;
int b = rand() % s;
int c = rand() % s;
char src[80];
snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
//int fd =
client->open(src, O_RDONLY);
}
return;
}
if (0) {
// rename fun
for (int i=0; i<100; i++) {
int s = 5;
int a = rand() % s;
int b = rand() % s;
int c = rand() % s;
int d = rand() % s;
int e = rand() % s;
int f = rand() % s;
char src[80];
char dst[80];
snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/file.%d", d, e, f);
client->rename(src, dst);
}
return;
}
if (1) {
// link fun
srand(0);
for (int i=0; i<100; i++) {
int s = 5;
int a = rand() % s;
int b = rand() % s;
int c = rand() % s;
int d = rand() % s;
int e = rand() % s;
int f = rand() % s;
char src[80];
char dst[80];
snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/newlink.%d", d, e, f);
client->link(src, dst);
}
srand(0);
for (int i=0; i<100; i++) {
int s = 5;
int a = rand() % s;
int b = rand() % s;
int c = rand() % s;
int d = rand() % s;
int e = rand() % s;
int f = rand() % s;
char src[80];
char dst[80];
snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/newlink.%d", d, e, f);
client->unlink(dst);
}
return;
}
// link fun
client->mknod("one", 0755);
client->mknod("two", 0755);
client->link("one", "three");
client->mkdir("dir", 0755);
client->link("two", "/dir/twolink");
client->link("dir/twolink", "four");
// unlink fun
client->mknod("a", 0644);
client->unlink("a");
client->mknod("b", 0644);
client->link("b", "c");
client->unlink("c");
client->mkdir("d", 0755);
client->unlink("d");
client->rmdir("d");
// rename fun
client->mknod("p1", 0644);
client->mknod("p2", 0644);
client->rename("p1","p2");
client->mknod("p3", 0644);
client->rename("p3","p4");
// check dest dir ambiguity thing
client->mkdir("dir1", 0755);
client->mkdir("dir2", 0755);
client->rename("p2","dir1/p2");
client->rename("dir1/p2","dir2/p2");
client->rename("dir2/p2","/p2");
// check primary+remote link merging
client->link("p2","p2.l");
client->link("p4","p4.l");
client->rename("p2.l","p2");
client->rename("p4","p4.l");
// check anchor updates
client->mknod("dir1/a", 0644);
client->link("dir1/a", "da1");
client->link("dir1/a", "da2");
client->link("da2","da3");
client->rename("dir1/a","dir2/a");
client->rename("dir2/a","da2");
client->rename("da1","da2");
client->rename("da2","da3");
// check directory renames
client->mkdir("dir3", 0755);
client->mknod("dir3/asdf", 0644);
client->mkdir("dir4", 0755);
client->mkdir("dir5", 0755);
client->mknod("dir5/asdf", 0644);
client->rename("dir3","dir4"); // ok
client->rename("dir4","dir5"); // fail
}
int SyntheticClient::thrash_links(const char *basedir, int dirs, int files, int depth, int n)
{
dout(1) << "thrash_links " << basedir << " " << dirs << " " << files << " " << depth
<< " links " << n
<< dendl;
if (time_to_stop()) return 0;
srand(0);
if (1) {
bool renames = true; // thrash renames too?
for (int k=0; k<n; k++) {
if (renames && rand() % 10 == 0) {
// rename some directories. whee!
int dep = (rand() % depth) + 1;
string src = basedir;
{
char t[80];
for (int d=0; d<dep; d++) {
int a = rand() % dirs;
snprintf(t, sizeof(t), "/dir.%d", a);
src += t;
}
}
string dst = basedir;
{
char t[80];
for (int d=0; d<dep; d++) {
int a = rand() % dirs;
snprintf(t, sizeof(t), "/dir.%d", a);
dst += t;
}
}
if (client->rename(dst.c_str(), "/tmp") == 0) {
client->rename(src.c_str(), dst.c_str());
client->rename("/tmp", src.c_str());
}
continue;
}
// pick a dest dir
string src = basedir;
{
char t[80];
for (int d=0; d<depth; d++) {
int a = rand() % dirs;
snprintf(t, sizeof(t), "/dir.%d", a);
src += t;
}
int a = rand() % files;
snprintf(t, sizeof(t), "/file.%d", a);
src += t;
}
string dst = basedir;
{
char t[80];
for (int d=0; d<depth; d++) {
int a = rand() % dirs;
snprintf(t, sizeof(t), "/dir.%d", a);
dst += t;
}
int a = rand() % files;
snprintf(t, sizeof(t), "/file.%d", a);
dst += t;
}
int o = rand() % 4;
switch (o) {
case 0:
client->mknod(src.c_str(), 0755);
if (renames) client->rename(src.c_str(), dst.c_str());
break;
case 1:
client->mknod(src.c_str(), 0755);
client->unlink(dst.c_str());
client->link(src.c_str(), dst.c_str());
break;
case 2: client->unlink(src.c_str()); break;
case 3: client->unlink(dst.c_str()); break;
//case 4: client->mknod(src.c_str(), 0755); break;
//case 5: client->mknod(dst.c_str(), 0755); break;
}
}
return 0;
}
if (1) {
// now link shit up
for (int i=0; i<n; i++) {
if (time_to_stop()) return 0;
char f[20];
// pick a file
string file = basedir;
if (depth) {
int d = rand() % (depth+1);
for (int k=0; k<d; k++) {
snprintf(f, sizeof(f), "/dir.%d", rand() % dirs);
file += f;
}
}
snprintf(f, sizeof(f), "/file.%d", rand() % files);
file += f;
// pick a dir for our link
string ln = basedir;
if (depth) {
int d = rand() % (depth+1);
for (int k=0; k<d; k++) {
snprintf(f, sizeof(f), "/dir.%d", rand() % dirs);
ln += f;
}
}
snprintf(f, sizeof(f), "/ln.%d", i);
ln += f;
client->link(file.c_str(), ln.c_str());
}
}
return 0;
}
void SyntheticClient::import_find(const char *base, const char *find, bool data)
{
dout(1) << "import_find " << base << " from " << find << " data=" << data << dendl;
/* use this to gather the static trace:
*
* find . -exec ls -dilsn --time-style=+%s \{\} \;
* or if it's wafl,
* find . -path ./.snapshot -prune -o -exec ls -dilsn --time-style=+%s \{\} \;
*
*/
if (base[0] != '-')
client->mkdir(base, 0755);
ifstream f(find);
assert(f.is_open());
int dirnum = 0;
while (!f.eof()) {
uint64_t ino;
int dunno, nlink;
string modestring;
int uid, gid;
off_t size;
time_t mtime;
string filename;
f >> ino;
if (f.eof()) break;
f >> dunno;
f >> modestring;
f >> nlink;
f >> uid;
f >> gid;
f >> size;
f >> mtime;
f.seekg(1, ios::cur);
getline(f, filename);
// ignore "."
if (filename == ".") continue;
// remove leading ./
assert(filename[0] == '.' && filename[1] == '/');
filename = filename.substr(2);
// new leading dir?
int sp = filename.find("/");
if (sp < 0) dirnum++;
//dout(0) << "leading dir " << filename << " " << dirnum << dendl;
if (dirnum % client->cct->_conf->num_client != client->get_nodeid()) {
dout(20) << "skipping leading dir " << dirnum << " " << filename << dendl;
continue;
}
// parse the mode
assert(modestring.length() == 10);
mode_t mode = 0;
switch (modestring[0]) {
case 'd': mode |= S_IFDIR; break;
case 'l': mode |= S_IFLNK; break;
default:
case '-': mode |= S_IFREG; break;
}
if (modestring[1] == 'r') mode |= 0400;
if (modestring[2] == 'w') mode |= 0200;
if (modestring[3] == 'x') mode |= 0100;
if (modestring[4] == 'r') mode |= 040;
if (modestring[5] == 'w') mode |= 020;
if (modestring[6] == 'x') mode |= 010;
if (modestring[7] == 'r') mode |= 04;
if (modestring[8] == 'w') mode |= 02;
if (modestring[9] == 'x') mode |= 01;
dout(20) << " mode " << modestring << " to " << oct << mode << dec << dendl;
if (S_ISLNK(mode)) {
// target vs destination
int pos = filename.find(" -> ");
assert(pos > 0);
string link;
if (base[0] != '-') {
link = base;
link += "/";
}
link += filename.substr(0, pos);
string target;
if (filename[pos+4] == '/') {
if (base[0] != '-')
target = base;
target += filename.substr(pos + 4);
} else {
target = filename.substr(pos + 4);
}
dout(10) << "symlink from '" << link << "' -> '" << target << "'" << dendl;
client->symlink(target.c_str(), link.c_str());
} else {
string f;
if (base[0] != '-') {
f = base;
f += "/";
}
f += filename;
if (S_ISDIR(mode)) {
client->mkdir(f.c_str(), mode);
} else {
int fd = client->open(f.c_str(), O_WRONLY|O_CREAT, mode & 0777);
assert(fd > 0);
if (data) {
client->write(fd, "", 0, size);
} else {
client->truncate(f.c_str(), size);
}
client->close(fd);
//client->chmod(f.c_str(), mode & 0777);
client->chown(f.c_str(), uid, gid);
struct utimbuf ut;
ut.modtime = mtime;
ut.actime = mtime;
client->utime(f.c_str(), &ut);
}
}
}
}
int SyntheticClient::lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name)
{
int r = client->lookup_hash(ino, dirino, name);
dout(0) << "lookup_hash(" << ino << ", #" << dirino << "/" << name << ") = " << r << dendl;
return r;
}
int SyntheticClient::lookup_ino(inodeno_t ino)
{
int r = client->lookup_ino(ino);
dout(0) << "lookup_ino(" << ino << ") = " << r << dendl;
return r;
}
int SyntheticClient::chunk_file(string &filename)
{
int fd = client->open(filename.c_str(), O_RDONLY);
int ret;
struct stat st;
client->fstat(fd, &st);
uint64_t size = st.st_size;
dout(0) << "file " << filename << " size is " << size << dendl;
Filer *filer = client->filer;
inode_t inode;
memset(&inode, 0, sizeof(inode));
inode.ino = st.st_ino;
ret = client->fdescribe_layout(fd, &inode.layout);
if (ret < 0)
return ret;
uint64_t pos = 0;
bufferlist from_before;
while (pos < size) {
int get = MIN(size-pos, 1048576);
Mutex flock("synclient chunk_file lock");
Cond cond;
bool done;
bufferlist bl;
flock.Lock();
Context *onfinish = new C_SafeCond(&flock, &cond, &done);
filer->read(inode.ino, &inode.layout, CEPH_NOSNAP, pos, get, &bl, 0, onfinish);
while (!done)
cond.Wait(flock);
flock.Unlock();
dout(0) << "got " << bl.length() << " bytes at " << pos << dendl;
if (from_before.length()) {
dout(0) << " including bit from previous block" << dendl;
pos -= from_before.length();
from_before.claim_append(bl);
bl.swap(from_before);
}
// ....
// keep last 32 bytes around
from_before.clear();
from_before.substr_of(bl, bl.length()-32, 32);
pos += bl.length();
}
client->close(fd);
return 0;
}
void SyntheticClient::mksnap(const char *base, const char *name)
{
client->mksnap(base, name);
}
void SyntheticClient::rmsnap(const char *base, const char *name)
{
client->rmsnap(base, name);
}
void SyntheticClient::mksnapfile(const char *dir)
{
client->mkdir(dir, 0755);
string f = dir;
f += "/foo";
int fd = client->open(f.c_str(), O_WRONLY|O_CREAT|O_TRUNC);
char buf[1048576*4];
client->write(fd, buf, sizeof(buf), 0);
client->fsync(fd, true);
client->close(fd);
string s = dir;
s += "/.snap/1";
client->mkdir(s.c_str(), 0755);
fd = client->open(f.c_str(), O_WRONLY);
client->write(fd, buf, 1048576*2, 1048576);
client->fsync(fd, true);
client->close(fd);
}