#include "TAS3File.h"
#include "THTTPMessage.h"
#include "TSocket.h"
#include "TROOT.h"
#include <errno.h>
#include <stdlib.h>
ClassImp(TAS3File)
TAS3File::TAS3File(const char *path, Option_t *) : TWebFile(path, "IO")
{
TString tpath = path;
Int_t begPath = 6, slash = 0, i = 0;
if (tpath.BeginsWith("as3://") == kFALSE) {
Error("TAS3File", "invalid path %s", path);
goto zombie;
}
while (i < 2 && begPath < tpath.Length()) {
slash = tpath.Index('/', begPath);
if (slash == kNPOS) {
Error("TAS3File","invalid path %s", path);
goto zombie;
}
switch(i){
case 0:
fServer = TUrl(TString(tpath(begPath,slash)));
break;
case 1:
fBucket = tpath(begPath,slash-begPath);
fRealName = "/" + tpath(slash+1, tpath.Length()-(slash+1));
}
i++;
begPath = slash+1;
}
fAuthPrefix = "AWS";
fAccessId = gSystem->Getenv("S3_ACCESS_ID");
fAccessKey = gSystem->Getenv("S3_ACCESS_KEY");
if (fAccessId == "" || fAccessKey == "") {
if (fAccessId == "") Error("TAS3File", "shell variable S3_ACCESS_ID not set");
if (fAccessKey == "") Error("TAS3File", "shell variable S3_ACCESS_KEY not set");
goto zombie;
}
Init(kFALSE);
return;
zombie:
MakeZombie();
gDirectory = gROOT;
}
Int_t TAS3File::GetHead()
{
THTTPMessage s3head = THTTPMessage(kHEAD, fRealName, GetBucket(),
GetUrl().GetHost(), GetAuthPrefix(),
GetAccessId(), GetAccessKey());
TString msg = s3head.GetRequest();
TUrl connurl;
fUrl = fServer;
if (fProxy.IsValid())
connurl = fProxy;
else
connurl = fUrl;
TSocket *s = 0;
for (Int_t i = 0; i < 5; i++) {
s = new TSocket(connurl.GetHost(), connurl.GetPort());
if (!s->IsValid()) {
delete s;
if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
s = 0;
gSystem->Sleep(i*10);
} else {
Error("GetHead", "cannot connect to host %s (errno=%d)", fUrl.GetHost(),
gSystem->GetErrno());
return -1;
}
} else
break;
}
if (!s)
return -1;
if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
Error("GetHead", "error sending command to host %s", fUrl.GetHost());
delete s;
return -1;
}
char line[8192];
Int_t n, ret = 0, redirect = 0;
while ((n = GetLine(s, line, sizeof(line))) >= 0) {
if (n == 0) {
if (gDebug > 0)
Info("GetHead", "got all headers");
delete s;
if (fBasicUrlOrg != "" && !redirect) {
SetMsgReadBuffer10();
fMsgGetHead = "";
}
if (ret < 0)
return ret;
if (redirect)
return GetHead();
return 0;
}
if (gDebug > 0)
Info("GetHead", "header: %s", line);
TString res = line;
if (res.BeginsWith("HTTP/1.")) {
if (res.BeginsWith("HTTP/1.1")) {
if (!fHTTP11) {
fMsgGetHead = "";
fMsgReadBuffer10 = "";
}
fHTTP11 = kTRUE;
}
TString scode = res(9, 3);
Int_t code = scode.Atoi();
if (code >= 500) {
if (code == 500)
fHasModRoot = kTRUE;
else {
ret = -1;
TString mess = res(13, 1000);
Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
}
} else if (code >= 400) {
if (code == 400)
ret = -3;
else if (code == 404)
ret = -2;
else {
ret = -1;
TString mess = res(13, 1000);
Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
}
} else if (code >= 300) {
if (code == 301 || code == 303)
redirect = 1;
else if (code == 302 || code == 307)
redirect = 2;
else {
ret = -1;
TString mess = res(13, 1000);
Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
}
} else if (code > 200) {
ret = -1;
TString mess = res(13, 1000);
Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
}
} else if (res.BeginsWith("Content-Length:")) {
TString slen = res(16, 1000);
fSize = slen.Atoll();
} else if (res.BeginsWith("Location:") && redirect) {
TString redir = res(10, 1000);
if (redirect == 2)
SetMsgReadBuffer10(redir, kTRUE);
else
SetMsgReadBuffer10(redir, kFALSE);
fMsgGetHead = "";
}
}
delete s;
return ret;
}
Bool_t TAS3File::ReadBuffer(char *buf, Int_t len)
{
return ReadBuffer10(buf,len);
}
Bool_t TAS3File::ReadBuffer10(char *buf, Int_t len)
{
const Int_t nbuf = 1;
Long64_t pos[nbuf];
pos[nbuf-1] = fOffset;
Int_t lens[nbuf];
lens[nbuf-1] = len;
THTTPMessage s3get = THTTPMessage(kGET, fRealName, GetBucket(),
GetUrl().GetHost(), GetAuthPrefix(),
GetAccessId(), GetAccessKey(),
0, pos, lens, nbuf);
TString msg = s3get.GetRequest();
Int_t n = GetFromWeb10(buf, len, msg);
if (n == -1)
return kTRUE;
if (n == -2) {
Error("ReadBuffer10", "%s does not exist", fBasicUrl.Data());
MakeZombie();
gDirectory = gROOT;
return kTRUE;
}
fOffset += len;
return kFALSE;
}