From: Aleš Křenek Date: Wed, 9 Apr 2008 11:50:47 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: glite-yaim-lb_R_4_0_2_1~113 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=d726a403d206b588601013543988fb38a3f755b7;p=jra1mw.git *** empty log message *** --- diff --git a/org.glite.lb.client-java/README b/org.glite.lb.client-java/README new file mode 100755 index 0000000..721db36 --- /dev/null +++ b/org.glite.lb.client-java/README @@ -0,0 +1,19 @@ +How to compile the source code. + +Run the script "compile.sh" with arguments: +All options are required except PATH_TO_JAVA, PREFIX and install or remove. + +-Dbuild.classes.dir="path to directory where .class files will be saved" \ +-Ddist.dir="path to directory where .jar file will be saved" \ +-Ddist.javadoc.dir="path to directory where documentation will be saved" \ +-Dproject.jobid-api-java="path to directory jobid-api-java" \ +-Dreference.jobid-api-java.jar="path to directory where jobid-api-java.jar is" \ +choose one of these: install or compile \ +PREFIX="path to directory where .so file will be saved" \ +PATH_TO_JAVA="path to directory where java is installed" \ + +How to run locallogger: +java -Djava.library.path=/path/to/shared/library -cp "/path/to/jobid-api-java.jar:/path/to/lb-client-java.jar" org.glite.test.Test + +If you don't set -Djava.library.path messages will not be send via unix socket but only written to specified file. + diff --git a/org.glite.lb.client-java/build.xml b/org.glite.lb.client-java/build.xml new file mode 100755 index 0000000..816febd --- /dev/null +++ b/org.glite.lb.client-java/build.xml @@ -0,0 +1,69 @@ + + + + + + Builds, tests, and runs the project lb-client-java. + + + diff --git a/org.glite.lb.client-java/compile.sh b/org.glite.lb.client-java/compile.sh new file mode 100755 index 0000000..215c28a --- /dev/null +++ b/org.glite.lb.client-java/compile.sh @@ -0,0 +1,13 @@ +#!/bin/bash +cmd1="$1"; +cmd2="$2"; +cmd3="$3"; +cmd4="$4"; +cmd5="$5"; +cmd6="$6"; +cmd7="$7"; +cmd7="$8"; + +ant $cmd1 $cmd2 $cmd3 $cmd4 $cmd5; +cd ./src_c +make $cmd6 $cmd7 $cmd8; diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/CheckedString.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/CheckedString.java new file mode 100755 index 0000000..8abf3d3 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/CheckedString.java @@ -0,0 +1,59 @@ +package org.glite.lb.client_java; + +/** + * Class which escapes \ and new line signs in string which is set as parameter + * in constructor + * + * @author Pavel Piskac (173297@mail.muni.cz) + * @version 15. 3. 2008 + */ +public class CheckedString { + + String checkedString; + + /** + * Creates new instance of CheckedString. + * + * @param checkedString string which will be converted + * @throws java.lang.IllegalArgumentException if checkedString is null + */ + public CheckedString(String checkedString) { + if (checkedString == null) { + throw new IllegalArgumentException("checkedString is null"); + } + + checkedString = checkedString.replaceAll("[\\\"]", "\\\\\""); + checkedString = checkedString.replaceAll("[\n]", "\\\\\\\\n"); + this.checkedString = checkedString; + } + + /** + * Gets converted string. + * + * @return converted string + */ + public String getCheckedString() { + return checkedString; + } + + /** + * Sets string which will be converted. + * + * @param checkedString string which will be converted. + */ + public void setCheckedString(String checkedString) { + checkedString = checkedString.replaceAll("[\\\"]", "\\\\\""); + checkedString = checkedString.replaceAll("[\n]", "\\\\\\\\n"); + this.checkedString = checkedString; + } + + /** + * Returns converted string. + * + * @return converted string + */ + public String toString() { + return checkedString; + } + +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/Context.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/Context.java new file mode 100755 index 0000000..07328b1 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/Context.java @@ -0,0 +1,440 @@ +package org.glite.lb.client_java; + +import java.net.UnknownHostException; +import java.util.Calendar; +import java.util.Random; +import org.glite.jobid.api_java.Jobid; + +/** + * Class representing a context for some job + * + * @author Pavel Piskac (173297@mail.muni.cz) + * @version 15. 3. 2008 + */ +public class Context { + + private int id; + private Sources source; + private int flag; + private String host; + private String user; + private String prog; + private String srcInstance; + private Jobid jobid; + private SeqCode seqCode; + private String message; + + /** + * Creates new instance of Context class. + */ + public Context() { + } + + /** + * Creates new instance of Context class. + * + * @param id message id, if null, random number is generated + * @param source one if paramaters of Sources enumeration + * @param flag + * @param host host name, if null or "", the name is get from host name of this computer + * @param user user name + * @param prog if null then is used "egd-wms" + * @param srcInstance if null then it is set as "" + * @param jobid + * @throws java.lang.IllegalArgumentException if source, user or jobid is null + * or flag < 0 + * + */ + public Context(int id, + Sources source, + int flag, + String host, + String user, + String prog, + String srcInstance, + Jobid jobid) { + if (id < 0) { + id = new Random().nextInt(); + } + + if (source == null) + { + throw new IllegalArgumentException("Context source"); + } + + if (flag < 0 || flag > 8) + { + throw new IllegalArgumentException("Context flag"); + } + + if (host == null || host.equals("")) + { + try { + host = java.net.InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + System.err.println(ex); + } + } + + if (user == null) + { + throw new IllegalArgumentException("Context user"); + } + + if (prog == null) { + prog = new String("edg-wms"); + } + + if (srcInstance == null) + { + srcInstance = new String(""); + } + + if (jobid == null) + { + throw new IllegalArgumentException("Context jobid"); + } + + this.id = id; + this.source = source; + this.flag = flag; + this.host = new CheckedString(host).toString(); + this.user = new CheckedString(user).toString(); + this.prog = new CheckedString(prog).toString(); + this.srcInstance = new CheckedString(srcInstance).toString(); + this.jobid = jobid; + } + + /** + * Converts Sources enum constants to defined string + * @param sourceEnum Sources enum constant + * @return String representation of Sources enum constants + * @throws IllegalArgumentException if wrong source type is set + */ + private String recognizeSource(Sources sourceEnum) { + switch (sourceEnum) { + case EDG_WLL_SOURCE_NONE: return "Undefined"; + case EDG_WLL_SOURCE_USER_INTERFACE: return "UserInterface"; + case EDG_WLL_SOURCE_NETWORK_SERVER: return "NetworkServer"; + case EDG_WLL_SOURCE_WORKLOAD_MANAGER: return "WorkloadManager"; + case EDG_WLL_SOURCE_BIG_HELPER: return "BigHelper"; + case EDG_WLL_SOURCE_JOB_SUBMISSION: return "JobController"; + case EDG_WLL_SOURCE_LOG_MONITOR: return "LogMonitor"; + case EDG_WLL_SOURCE_LRMS: return "LRMS"; + case EDG_WLL_SOURCE_APPLICATION: return "Application"; + case EDG_WLL_SOURCE_LB_SERVER: return "LBServer"; + default: throw new IllegalArgumentException("wrong source type"); + } + } + + public Sources stringToSources(String source) { + if (source.equals("EDG_WLL_SOURCE_NONE")) return Sources.EDG_WLL_SOURCE_NONE; + if (source.equals("EDG_WLL_SOURCE_USER_INTERFACE")) return Sources.EDG_WLL_SOURCE_USER_INTERFACE; + if (source.equals( "EDG_WLL_SOURCE_NETWORK_SERVER")) return Sources.EDG_WLL_SOURCE_NETWORK_SERVER; + if (source.equals("EDG_WLL_SOURCE_WORKLOAD_MANAGER")) return Sources.EDG_WLL_SOURCE_WORKLOAD_MANAGER; + if (source.equals("EDG_WLL_SOURCE_BIG_HELPER")) return Sources.EDG_WLL_SOURCE_BIG_HELPER; + if (source.equals("EDG_WLL_SOURCE_JOB_SUBMISSION")) return Sources.EDG_WLL_SOURCE_JOB_SUBMISSION; + if (source.equals("EDG_WLL_SOURCE_LOG_MONITOR")) return Sources.EDG_WLL_SOURCE_LOG_MONITOR; + if (source.equals("EDG_WLL_SOURCE_LRMS")) return Sources.EDG_WLL_SOURCE_LRMS; + if (source.equals("EDG_WLL_SOURCE_APPLICATION")) return Sources.EDG_WLL_SOURCE_APPLICATION; + if (source.equals("EDG_WLL_SOURCE_LB_SERVER")) return Sources.EDG_WLL_SOURCE_LB_SERVER; + throw new IllegalArgumentException("wrong source type"); + + } + + /** + * Creates message prepared to send + * @param event event for which is message generated + * @throws IllegalArgumentException if event, source, user or job is null + * or flag < 0 + */ + public void log(Event event) { + if (event == null) { + throw new IllegalArgumentException("Context event"); + } + + if (source == null) + { + throw new IllegalArgumentException("Context source"); + } + + if (flag < 0 || flag > 8) + { + throw new IllegalArgumentException("Context flag"); + } + + if (host == null || host.equals("")) + { + try { + host = java.net.InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + System.err.println(ex); + } + } + + if (prog == null) { + prog = new String("edg-wms"); + } + + if (user == null) + { + throw new IllegalArgumentException("Context user"); + } + + if (srcInstance == null) + { + srcInstance = new String(""); + } + + if (jobid == null) + { + throw new IllegalArgumentException("Context jobid"); + } + + String output; + String date = ""; + String tmp; + date = String.valueOf(Calendar.getInstance().get(Calendar.YEAR)); + tmp = String.valueOf(Calendar.getInstance().get(Calendar.MONTH) + 1); + date += "00".substring(0, 2 - tmp.length ()) + tmp; + tmp = String.valueOf(Calendar.getInstance().get(Calendar.DATE)); + date += "00".substring(0, 2 - tmp.length ()) + tmp; + tmp = String.valueOf(Calendar.getInstance().get(Calendar.HOUR)); + date += "00".substring(0, 2 - tmp.length ()) + tmp; + tmp = String.valueOf(Calendar.getInstance().get(Calendar.MINUTE)); + date += "00".substring(0, 2 - tmp.length ()) + tmp; + tmp = String.valueOf(Calendar.getInstance().get(Calendar.SECOND)); + date += "00".substring(0, 2 - tmp.length ()) + tmp; + date += "."; + tmp = String.valueOf(Calendar.getInstance().get(Calendar.MILLISECOND)); + String tmp2 = "000".substring(0, 3 - tmp.length ()) + tmp; + date += tmp2 + "000000".substring(tmp.length (), 6); + + seqCode.setPardOfSeqCode(flag, seqCode.getPardOfSeqCode(flag)+1); + + output = ("DG.LLLID=" + id + + " DG.USER=\"" + user + "\"" + + " DATE=" + date + + " HOST=\"" + host + "\"" + + " PROG=" + prog + + " LVL=SYSTEM" + + " DG.PRIORITY=0" + + " DG.SOURCE=\"" + recognizeSource(source) + "\"" + + " DG.SRC_INSTANCE=\"" + srcInstance + "\"" + + " DG.EVNT=\"" + event.getEventType() + "\"" + + " DG.JOBID=\"" + jobid + "\"" + + " DG.SEQCODE=\"" + seqCode + "\"" + + event.ulm()); + + this.message = output; + } + + /** + * Return flag which represents which part of sequence code will be changes + * + * @return flag + */ + public int getFlag() { + return flag; + } + + /** + * Set flag which represents which part of sequence code will be changes + * + * @param flag + * @throws java.lang.IllegalArgumentException if flag is lower than 0 + */ + public void setFlag(int flag) { + if (flag < 0 || flag > 8) + { + throw new IllegalArgumentException("Context flag"); + } + + this.flag = flag; + } + + /** + * Returns host name + * + * @return host name + */ + public String getHost() { + return host; + } + + /** + * Sets host name + * @param host host name + * @throws java.lang.IllegalArgumentException if host is null + */ + public void setHost(String host) { + if (host == null) + { + throw new IllegalArgumentException("Context host"); + } + + this.host = host; + } + + /** + * Gets message id. + * + * @return message id + */ + public int getId() { + return id; + } + + /** + * Sets message id. + * + * @param id message id + * @throws java.lang.IllegalArgumentException if id is lower than 0 + */ + public void setId(int id) { + if (id < 0) + { + throw new IllegalArgumentException("Context id"); + } + this.id = id; + } + + /** + * Gets jobid. + * + * @return jobid + */ + public Jobid getJobid() { + return jobid; + } + + /** + * Sets jobid. + * + * @param jobid + * @throws java.lang.IllegalArgumentException if jobid is null + */ + public void setJobid(Jobid jobid) { + if (jobid == null) + { + throw new IllegalArgumentException("Context jobid"); + } + + this.jobid = jobid; + } + + /** + * Gets message which is prepared to send. + * @return message + */ + public String getMessage() { + return message; + } + + /** + * Gets prog. + * @return prog + */ + public String getProg() { + return prog; + } + + /** + * Sets prog, if prog is null then is set default value "edg-wms" + * @param prog + */ + public void setProg(String prog) { + if (prog == null) { + prog = new String("edg-wms"); + } + + this.prog = (new CheckedString(prog)).toString(); + } + + /** + * Gets sequence code. + * + * @return sequence code + */ + public SeqCode getSeqCode() { + return seqCode; + } + + /** + * Sets sequence code. + * @param seqCode sequence code + * @throws java.lang.IllegalArgumentException if seqCode is null + */ + public void setSeqCode(SeqCode seqCode) { + if (seqCode == null) { + throw new IllegalArgumentException("Context seqCode"); + } + + this.seqCode = seqCode; + } + + /** + * Gets source. + * @return source + */ + public Sources getSource() { + return source; + } + + /** + * Sets source + * @param source source + * @throws java.lang.IllegalArgumentException if source is null + */ + public void setSource(Sources source) { + if (source == null) + { + throw new IllegalArgumentException("Context source"); + } + + this.source = source; + } + + /** + * Gets srcInstance. + * @return srcInstance + */ + public String getSrcInstance() { + return srcInstance; + } + + /** + * Sets srcInstace, if srcInstace null then is set "". + * @param srcInstance srcInstance + */ + public void setSrcInstance(String srcInstance) { + if (srcInstance == null) + { + srcInstance = new String(""); + } + + this.srcInstance = new CheckedString(srcInstance).toString(); + } + + /** + * Gets user name. + * @return user name + */ + public String getUser() { + return user; + } + + /** + * Sets user name. + * @param user user name + * @throws java.lang.IllegalArgumentException if user is null + */ + public void setUser(String user) { + if (user == null) + { + throw new IllegalArgumentException("Context user"); + } + + this.user = (new CheckedString(user)).toString(); + } +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/ContextIL.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/ContextIL.java new file mode 100755 index 0000000..79c6370 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/ContextIL.java @@ -0,0 +1,369 @@ +package org.glite.lb.client_java; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import org.glite.jobid.api_java.Jobid; + +/** + * Class which is used to send messages to inter-logger using unix socket. + * + * @author Pavel Piskac (173297@mail.muni.cz) + */ +public class ContextIL extends Context { + + private String pathToSocket; + private String pathToNativeLib; + private String prefix; + private int repeatWriteToFile = 5; + private int connAttempts = 3; + private int timeout = 3; + private Boolean useUnixSocket = true; + + //navod http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html + //native method which is written in C and imported to Java + native int sendToSocket(String socket_path, + long filepos, + String msg, + int msg_size, + int conn_attempts, + int timeout); + + /** + * Creates new instance of ContextIL. + */ + public ContextIL() { + } + + /** + * Creates new instance of ContextIL. + * + * @param pathToSocket path to unix socket + * @param prefix path where are stored messages + */ + public ContextIL(String pathToSocket, String prefix) { + this.prefix = new CheckedString(prefix).toString(); + this.pathToSocket = new CheckedString(pathToSocket).toString(); + } + + /** + * Creates new instance of ContextIL. + * + * @param id message id, if null, random number is generated + * @param source one if paramaters of Sources enumeration + * @param flag + * @param host host name, if null or "", the name is get from host name of this computer + * @param user user name + * @param prog if null then is used "egd-wms" + * @param srcInstance if null then it is set as "" + * @param jobid jobid + * @param path path to unix socket + * @param prefix path where are stored messages + * @throws java.lang.IllegalArgumentException if source, user, jobid, prefix + * or path is null or flag < 0 + */ + public ContextIL(int id, + Sources source, + int flag, + String host, + String user, + String prog, + String srcInstance, + Jobid jobid, + String path, + String prefix) { + + super(id, source, flag, host, user, prog, srcInstance, jobid); + + if (prefix == null) { + throw new IllegalArgumentException("ContextIL prefix"); + } + + if (path == null) { + throw new IllegalArgumentException("ContextIL path"); + } + + this.prefix = new CheckedString(prefix).toString(); + this.pathToSocket = new CheckedString(pathToSocket).toString(); + } + + /** + * Writes message to a file and returns original size of this file + * + * @param prefix file path + * @param message message which will be written + * @return size of the file before writing the data + */ + private Long writeToFile(String prefix, String message) { + FileWriter fileWriter = null; + Long fileLength = null; + RandomAccessFile raf = null; + FileLock fileLock = null; + File file; + + for (int i = 0; i < repeatWriteToFile; i++) { + try { + file = new File(prefix); + raf = new RandomAccessFile(file, "rw"); + FileChannel fileChannel = raf.getChannel(); + + fileLock = fileChannel.tryLock(); + if (fileLock != null) { + if (!file.exists()) { + continue; + } + fileLength = raf.length(); + fileWriter = new FileWriter(file, true); + //true means append data at the end of file + + BufferedWriter bufferedFileWriter = new BufferedWriter(fileWriter); + + bufferedFileWriter.write(message + '\n'); + bufferedFileWriter.flush(); + + if (file.exists()) { + break; + } + } + } catch (FileNotFoundException ex) { + System.err.println(ex); + } catch (IOException ex) { + System.err.println(ex); + } catch (Exception ex) { + System.err.println(ex); + } finally { + if (fileLock != null) { + try { + fileLock.release(); + } catch (IOException ex) { + System.err.println(ex); + } + } + + try { + raf.close(); + } catch (IOException ex) { + System.err.println(ex); + } catch (NullPointerException ex) { + System.err.println(ex); + } + } + } + + return fileLength; + } + + /** + * Writes file position and message to specified socket. + * + * @param pathToSocket path to unix socket + * @param fileSize size of the file before new message was written there + * @param message message which will be send + * @param conn_attempts count of connection attempts + * @param time_out connection timeout + */ + private void writeToSocket(String pathToSocket, + long fileSize, + String message) { + + if (useUnixSocket) { + try { + System.loadLibrary("sendviasocket"); + message += '\n'; + sendToSocket(pathToSocket, + fileSize, + message, + message.length(), + connAttempts, + timeout); + + } catch (UnsatisfiedLinkError ex) { + useUnixSocket = false; + System.err.println(ex); + } + } + } + + /** + * Writes event message to the file and socket. + * + * @param event event + * @throws java.lang.IllegalArgumentException if event, prefix or path + */ + @Override + public void log(Event event) { + if (event == null) { + throw new IllegalArgumentException("ContextIL event"); + } + + if (prefix == null) { + throw new IllegalArgumentException("ContextIL prefix"); + } + + if (pathToSocket == null || pathToSocket.equals("")) { + pathToSocket = new String(""); + useUnixSocket = false; + } + + if (pathToNativeLib == null || pathToNativeLib.equals("")) { + pathToNativeLib = new String(""); + useUnixSocket = false; + } + + super.log(event); + String message = super.getMessage(); + + Long fileLength = writeToFile(prefix, message); + + writeToSocket(pathToSocket, fileLength, message); + } + + /** + * Gets path to socket. + * + * @return pathToSocket to socket + */ + public String getPathToSocket() { + return pathToSocket; + } + + /** + * Sets path to socket. + * + * @param pathToSocket path to socket + * @throws java.lang.IllegalArgumentException if path is null + */ + public void setPathToSocket(String pathToSocket) { + if (pathToSocket == null) { + throw new IllegalArgumentException("ContextIL pathToSocket"); + } + + this.pathToSocket = new CheckedString(pathToSocket).toString(); + } + + /** + * Gets path to nativelib file which is needed to send messages via unix socket + * + * @return pathToNativeLib to native library (libnativelib.so) + */ + public String getPathToNativeLib() { + return pathToNativeLib; + } + + /** + * Sets path to nativelib file which is needed to send messages via unix socket + * @param pathToNativeLib path to shared library (libnativelib.so) + */ + public void setPathToNativeLib(String pathToNativeLib) { + if (pathToNativeLib == null) { + throw new IllegalArgumentException("ContextIL pathToNativeLib"); + } + + this.pathToNativeLib = pathToNativeLib; + } + + /** + * Gets path where are stored messages. + * + * @return path where are stored messages + */ + public String getPrefix() { + return prefix; + } + + /** + * Sets path where are stored messages. + * + * @param prefix path where are stored messages + */ + public void setPrefix(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("ContextIL prefix"); + } + + this.prefix = new CheckedString(prefix).toString(); + } + + /** + * Gets count of repeated write to file if some exception is thrown. + * + * @return count of repeated write to file + */ + public int getRepeatWriteToFile() { + return repeatWriteToFile; + } + + /** + * Sets count of repeated write to file if some exception is thrown. + * + * @param repeatWriteToFile count of repeated write to file + */ + public void setRepeatWriteToFile(int repeatWriteToFile) { + if (repeatWriteToFile < 1) { + throw new IllegalArgumentException("ContextIL repeatWriteToFile"); + } + + this.repeatWriteToFile = repeatWriteToFile; + } + + /** + * Gets count of connection attempts which is used while sending the message via unix socket. + * + * @return count of connection attempts + */ + public int getConnAttempts() { + return connAttempts; + } + + /** + * Sets count of connection attempts while sending the message via unix socket. + * + * @param connAttempts count of connection attempts + */ + public void setConnAttempts(int connAttempts) { + if (connAttempts < 1) { + throw new IllegalArgumentException("ContextIL conn_attempts"); + } + + this.connAttempts = connAttempts; + } + + /** + * Gets timeout which is used while sending the message via unix socket. + * + * @return timeout + */ + public int getTimeout() { + return timeout; + } + + /** + * Sets timeout which is used while sending the message via unix socket. + * + * @param timeout timeout + */ + public void setTimeout(int timeout) { + if (timeout < 1) { + throw new IllegalArgumentException("ContextIL time_out"); + } + + this.timeout = timeout; + } + + public Boolean getUseUnixSocket() { + return useUnixSocket; + } + + public void setUseUnixSocket(Boolean useUnixSocket) { + if (useUnixSocket == null) { + throw new IllegalArgumentException("ContextIL useUnixSocket"); + } + + this.useUnixSocket = useUnixSocket; + } +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/ContextProxy.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/ContextProxy.java new file mode 100755 index 0000000..87809a5 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/ContextProxy.java @@ -0,0 +1,278 @@ +package org.glite.lb.client_java; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.RandomAccessFile; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.util.ArrayList; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import org.glite.jobid.api_java.Jobid; + +/** + * + * @author xpiskac + */ +public class ContextProxy extends Context { + + private String address; + private int port; + private String prefix; + private int repeatWriteToFile = 5; + private int timeout = 30000; + private String pathToCertificate; + private String password; + + public ContextProxy() { + } + + public ContextProxy(String address, int port, String prefix) { + this.prefix = new CheckedString(prefix).toString(); + this.address = new CheckedString(address).toString(); + this.port = port; + } + + public ContextProxy(int id, + Sources source, + int flag, + String host, + String user, + String prog, + String srcInstance, + Jobid jobid, + String address, + int port, + String prefix) { + + super(id, source, flag, host, user, prog, srcInstance, jobid); + + if (prefix == null) { + throw new IllegalArgumentException("ContextProxy prefix"); + } + if (address == null) { + throw new IllegalArgumentException("ContextProxy socket"); + } + if (port < 0) { + throw new IllegalArgumentException("ContextProxy port"); + } + + this.prefix = new CheckedString(prefix).toString(); + this.address = new CheckedString(address).toString(); + } + + /** + * Writes message to a file and returns size of this file before writing the + * data + * @param prefix file path + * @param message message which will be written + * @return size of the file before writing the data + */ + private Long writeToFile(String prefix, String message) { + FileWriter fileWriter = null; + Long fileLength = null; + RandomAccessFile raf = null; + FileLock fileLock = null; + File file; + + for (int i = 0; i < repeatWriteToFile; i++) { + try { + file = new File(prefix); + raf = new RandomAccessFile(file, "rw"); + FileChannel fileChannel = raf.getChannel(); + + fileLock = fileChannel.tryLock(); + if (fileLock != null) { + if (!file.exists()) { + continue; + } + fileLength = raf.length(); + fileWriter = new FileWriter(file, true); + //true means append data to the end of file + + BufferedWriter bufferedFileWriter = new BufferedWriter(fileWriter); + + bufferedFileWriter.write(message + '\n'); + bufferedFileWriter.flush(); + + if (file.exists()) { + break; + } + } + } catch (FileNotFoundException ex) { + System.err.println(ex); + } catch (IOException ex) { + System.err.println(ex); + } catch (Exception ex) { + System.err.println(ex); + } finally { + if (fileLock != null) { + try { + fileLock.release(); + } catch (IOException ex) { + System.err.println(ex); + } + } + + try { + raf.close(); + } catch (IOException ex) { + System.err.println(ex); + } + } + } + + return fileLength; + } + + private void writeToSocket(String address, int port, int timeout, long fileSize, String message) { + // From http://sci.civ.zcu.cz/java/lbexample.zip ExampleSSLSocketFactory.java + SSLSocketFactory sslFactory = null; + try { + SSLSocket socket = (SSLSocket) sslFactory.createSocket(); + //enable only SSLv3 + socket.setEnabledProtocols(new String[]{"SSLv3"}); // SSLv2Hello, SSLv3,TLSv1 + //enable only ciphers without RC4 (some bug in JSSE?) + String[] ciphers = socket.getEnabledCipherSuites(); + ArrayList al = new ArrayList(ciphers.length); + for (int i = 0; i < ciphers.length; i++) { + if (ciphers[i].indexOf("RC4") == -1) al.add(ciphers[i]); + } + socket.setEnabledCipherSuites((String [])al.toArray(new String[al.size()])); + //connect as client + socket.setUseClientMode(true); + socket.setSoTimeout(timeout); //read timeout + socket.connect(new InetSocketAddress(address, port), timeout); //connect timeout + PrintWriter osw = + new PrintWriter(socket.getOutputStream(), true); + osw.println(fileSize); + osw.println(message); + osw.close(); + socket.close(); + } catch (UnknownHostException ex) { + System.err.println("unknown host " + ex); + } catch (IOException ex) { + System.err.println("io exception " + ex); + } + } + + @Override + public void log(Event event) { + if (event == null) { + throw new IllegalArgumentException("ContextProxy event"); + } + + if (prefix == null) { + throw new IllegalArgumentException("ContextProxy prefix"); + } + + if (address == null) { + throw new IllegalArgumentException("ContextProxy socket"); + } + + if (port < 0) { + throw new IllegalArgumentException("ContextProxy port"); + } + + super.log(event); + String message = super.getMessage(); + + Long fileSize = writeToFile(prefix, message); + + //writeToSocket(address, port, timeout, fileSize, message); + + //SSLSend sslSend = new SSLSend(keyStoreSender, password, address, + // port, timeout, fileSize, message); + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + if (prefix == null) { + throw new IllegalArgumentException("ContextProxy address"); + } + + this.address = new CheckedString(address).toString(); + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + if (port < 0) { + throw new IllegalArgumentException("ContextProxy port"); + } + this.port = port; + } + + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("ContextProxy prefix"); + } + + this.prefix = new CheckedString(prefix).toString(); + } + + public int getRepeatWriteToFile() { + return repeatWriteToFile; + } + + public void setRepeatWriteToFile(int repeatWriteToFile) { + if (repeatWriteToFile < 1) { + throw new IllegalArgumentException("ContextProxy repeatWriteToFile"); + } + + this.repeatWriteToFile = repeatWriteToFile; + } + + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + if (timeout < 0) { + throw new IllegalArgumentException("ContextProxy timout"); + } + this.timeout = timeout; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + if (password == null) { + throw new IllegalArgumentException("ContextProxy password"); + } + + this.password = password; + } + + public String getPathToCertificate() { + return pathToCertificate; + } + + public void setPathToCertificate(String pathToCertificate) { + if (pathToCertificate == null) { + throw new IllegalArgumentException("ContextProxy pathToCertificate"); + } + + this.pathToCertificate = pathToCertificate; + } + + +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/Event.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/Event.java new file mode 100755 index 0000000..5c8cfbc --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/Event.java @@ -0,0 +1,23 @@ +package org.glite.lb.client_java; + +/** + * Abstract class which serves as base for all events. + * + * @author Pavel Piskac (173297@mail.muni.cz) + */ +public abstract class Event { + + /** + * When implemented, this method returns string which is specific for each event. + * + * @return specific string + */ + public abstract String ulm(); + + /** + * When implemented, this method returns name of event type. + * + * @return name of event + */ + public abstract String getEventType(); +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/Running.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/Running.java new file mode 100755 index 0000000..c44a04e --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/Running.java @@ -0,0 +1,68 @@ +package org.glite.lb.client_java; + +/** + * Class which represents event "running". + * + * @author Pavel Piskac (173297@mail.muni.cz) + */ +public class Running extends Event { + + private String node; + + /** + * Creates new instance. + */ + public Running() { + } + + /** + * Creates new instance, where is set variable node. + * @param node node + */ + public Running(String node) { + if (node == null) { + node = new String(""); + } + + this.node = node; + } + + /** + * Returns part of message, which will be joined to the of the message. + * Its format is " DG.RUNNING.NODE=\"" + node + "\"" + * @return part of message which is specific for event running + */ + public String ulm() { + return (" DG.RUNNING.NODE=\"" + node + "\""); + } + + /** + * Returns event type specific for event running ("Running"). + * + * @return event type + */ + public String getEventType() { + return "Running"; + } + + /** + * Gets node. + * + * @return node + */ + public String getNode() { + return node; + } + + /** + * Sets node, if node is null then it is "" set. + * @param node + */ + public void setNode(String node) { + if (node == null) { + node = new String(""); + } + + this.node = new CheckedString(node).toString(); + } +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/SeqCode.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/SeqCode.java new file mode 100755 index 0000000..2ecbff0 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/SeqCode.java @@ -0,0 +1,76 @@ +package org.glite.lb.client_java; + +/** + * + * @author xpiskac + */ +public class SeqCode { + + private int[] seqCode = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + + public SeqCode() { + } + + public int[] getSeqCode() { + return seqCode; + } + + public void setSeqCode(int[] seqCode) { + this.seqCode = seqCode; + } + + public int getPardOfSeqCode(int part) { + if (part < 0 || part > 9) { + throw new IllegalArgumentException("part"); + } + + return seqCode[part]; + } + + public void setPardOfSeqCode(int part, int value) { + if (part < 0 || part > 9) { + throw new IllegalArgumentException("part"); + } + + seqCode[part] = value; + } + + public String toString() { + String tmp = Integer.toString(seqCode[0]); + String output = "UI="; + output += "000000".substring(0, 6 - tmp.length ()) + tmp; + output += ":"; + output += "NS="; + tmp = Integer.toString(seqCode[1]); + output += "0000000000".substring(0, 10 - tmp.length ()) + tmp; + output += ":"; + output += "WM="; + tmp = Integer.toString(seqCode[2]); + output += "0000000000".substring(0, 6 - tmp.length ()) + tmp; + output += ":"; + output += "BH="; + tmp = Integer.toString(seqCode[3]); + output += "0000000000".substring(0, 10 - tmp.length ()) + tmp; + output += ":"; + output += "JSS="; + tmp = Integer.toString(seqCode[4]); + output += "0000000000".substring(0, 6 - tmp.length ()) + tmp; + output += ":"; + output += "LM="; + tmp = Integer.toString(seqCode[5]); + output += "0000000000".substring(0, 6 - tmp.length ()) + tmp; + output += ":"; + output += "LMRS="; + tmp = Integer.toString(seqCode[6]); + output += "0000000000".substring(0, 6 - tmp.length ()) + tmp; + output += ":"; + output += "APP="; + tmp = Integer.toString(seqCode[7]); + output += "0000000000".substring(0, 6 - tmp.length ()) + tmp; + output += ":"; + output += "LBS="; + tmp = Integer.toString(seqCode[8]); + output += "0000000000".substring(0, 6 - tmp.length ()) + tmp; + return output; + } +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/Sources.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/Sources.java new file mode 100755 index 0000000..651c471 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/Sources.java @@ -0,0 +1,19 @@ +package org.glite.lb.client_java; + +/** + * Enum which represents type if sources. + * + * @author Pavel Piskac (173297@mail.muni.cz) + */ +public enum Sources { + EDG_WLL_SOURCE_NONE, /* uninitialized value */ + EDG_WLL_SOURCE_USER_INTERFACE, + EDG_WLL_SOURCE_NETWORK_SERVER, + EDG_WLL_SOURCE_WORKLOAD_MANAGER, + EDG_WLL_SOURCE_BIG_HELPER, + EDG_WLL_SOURCE_JOB_SUBMISSION, + EDG_WLL_SOURCE_LOG_MONITOR, + EDG_WLL_SOURCE_LRMS, + EDG_WLL_SOURCE_APPLICATION, + EDG_WLL_SOURCE_LB_SERVER +} diff --git a/org.glite.lb.client-java/src/org/glite/lb/client_java/Transfer.java b/org.glite.lb.client-java/src/org/glite/lb/client_java/Transfer.java new file mode 100755 index 0000000..a9c6770 --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/lb/client_java/Transfer.java @@ -0,0 +1,100 @@ +package org.glite.lb.client_java; + +/** + * + * @author xpiskac + */ +public class Transfer extends Event { + + private String destination; + private String destHostname; + private String destInstance; + private String jobDescription; + private String result; + private String reason; + private String destJobid; + + public Transfer() { + } + + public Transfer (String destination, + String destHostname, + String destInstance, + String jobDescription, + String result, + String reason, + String destJobid) { + + this.destination = destination; + this.destHostname = destHostname; + this.destInstance = destInstance; + this.jobDescription = jobDescription; + this.result = result; + this.reason = reason; + this.destJobid = destJobid; + } + + public String ulm() { + return null; //zatim neimplementovano + } + + public String getEventType() { + return "Transfer"; + } + + public String getDestHostname() { + return destHostname; + } + + public void setDestHostname(String destHostname) { + this.destHostname = destHostname; + } + + public String getDestInstance() { + return destInstance; + } + + public void setDestInstance(String destInstance) { + this.destInstance = destInstance; + } + + public String getDestJobid() { + return destJobid; + } + + public void setDestJobid(String destJobid) { + this.destJobid = destJobid; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public String getJobDescription() { + return jobDescription; + } + + public void setJobDescription(String jobDescription) { + this.jobDescription = jobDescription; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } +} diff --git a/org.glite.lb.client-java/src/org/glite/test/Test.java b/org.glite.lb.client-java/src/org/glite/test/Test.java new file mode 100755 index 0000000..23eda6d --- /dev/null +++ b/org.glite.lb.client-java/src/org/glite/test/Test.java @@ -0,0 +1,178 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.glite.test; + +import java.util.Random; +import org.glite.jobid.api_java.Jobid; +import org.glite.lb.client_java.ContextIL; +import org.glite.lb.client_java.Running; +import org.glite.lb.client_java.SeqCode; + +/** + * + * @author xpiskac + */ +public class Test { + + public static void main(String[] args) { + + //how Jobid class works + /* //unique part is automatically generated + Jobid jobid = new Jobid("https://somewhere.cz", 5000); + System.out.println("bkserver "+ jobid.getBkserver()); + System.out.println("port "+ jobid.getPort()); + System.out.println("unique "+ jobid.getUnique()); + System.out.println("-------------------"); + + //unique part is set by user + Jobid jobid2 = new Jobid("https://somewhere.cz", 5000, "my_unique_part"); + System.out.println("bkserver "+ jobid2.getBkserver()); + System.out.println("port "+ jobid2.getPort()); + System.out.println("unique "+ jobid2.getUnique()); + System.out.println("-------------------"); + + //whole jobid is set by user and then parsed + Jobid jobid3 = new Jobid("https://somewhere.cz:5000/my_unique_part"); + System.out.println("bkserver "+ jobid3.getBkserver()); + System.out.println("port "+ jobid3.getPort()); + System.out.println("unique "+ jobid3.getUnique()); + System.out.println("-------------------"); + + //each part is set separately + Jobid jobid4 = new Jobid(); + jobid4.setBkserver("https://somewhere.cz"); + jobid4.setPort(5000); + jobid4.setUnique("my_unique_part"); + System.out.println("bkserver "+ jobid4.getBkserver()); + System.out.println("port "+ jobid4.getPort()); + System.out.println("unique "+ jobid4.getUnique()); + System.out.println("-------------------"); + + */ + if (args.length == 0) { + System.out.println("How to use test class:\n" + + "you have to set 10 arguments in this order, if the choice is optional \"\" or text has to be set:\n" + + "1. jobid in format \"https://somewhere:port/unique_part\" (required)\n" + + "2. path to shared library written in c to be able to send messages via unix socket (optional)\n" + + "3. source, enum constant from class Sources (required)\n" + + "4. flag determines which part of sequence code will be increased\n" + + "5. host name, if it is \"\" then is set name of the computer where is test class running (optional)\n" + + "6. user name (required)\n" + + "7. PID of running process (optional)\n" + + "8. path to directory where will be saved files with events for each job (required)\n" + + "9. path to unix socket (required if path to shared library is set)\n" + + "10. description for event in this case event running (optional)\n"); + } else { + /* Create new instance of jobid, you can use other constructors too (see org.glite.jobid.api_java.Jobid.java) + * Examples: + * Jobid jobid = new Jobid("https://skurut68-2.cesnet.cz:9000/paja6_test2"); + * Jobid jobid = new Jobid("https://skurut68-2.cesnet.cz", 9000, "paja6_test2"); + * Jobid jobid = new Jobid("https://skurut68-2.cesnet.cz", 9000); //unique part is automatically generated + * Jobid jobid = new Jobid(); + * jobid.setBkserver("https://skurut68-2.cesnet.cz"); + * jobid.setPort(9000); + * jobid.setUnique("paja6_test2"); + */ + Jobid jobid = new Jobid(args[0]); + + /* Create sequence code + * Example: + * SeqCode seqCode = new SeqCode(); + * Then you can set some parts + * Example: + * seqCode.setPardOfSeqCode(0, 95); + * or whole sequence number + * Example: + * int[] seqCodeArray = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + * seqCode.setSeqCode(seqCodeArray); + */ + SeqCode seqCode = new SeqCode(); + + /* Choose type of sending a log messages (at this time is implemented only ContextIL class) + * You can choose from some constructors (see org.glite.lb.client_java.ContextIL class) + */ + ContextIL ctx = new ContextIL(); + + /* If you chose emtpy ContextIL constructor you have to set some attributes. + * One of them is pathToNativeLib which sais where java can find shared library written in c. + * Example: ctx.setPathToNativeLib("/home/paja6/locallogger/build/classes/org/glite/lb/"); + */ + ctx.setPathToNativeLib(args[1]); + + /* Id of the message is some random unique number. + */ + ctx.setId(new Random().nextInt(99999999)); + + /* Source indicates source of the message, it is constant from org.glite.lb.client_java.Sources class + * Example: ctx.setSource(ctx.stringToSources("EDG_WLL_SOURCE_LRMS")); + */ + ctx.setSource(ctx.stringToSources(args[2])); + + /* Flag tells which part of the sequence number will be increased. It is a number in range from 0 to 8 + * Example: ctx.setFlag(0); + */ + ctx.setFlag(new Integer(args[3])); + + /* Name of the computer where is locallogger running + * Example: ctx.setHost("pelargir.ics.muni.cz"); + */ + ctx.setHost(args[4]); + + /* Name of the user who owns the job. + * Example: ctx.setUser("Pavel Piskac"); + */ + ctx.setUser(args[5]); + + /* TODO co to vlastne znamena? + * Mostly "" is set + * Example: ctx.setSrcInstance(""); + */ + ctx.setSrcInstance(args[6]); + + /* Set the jobid for the context. + */ + ctx.setJobid(jobid); + + /* Set the jobid for the context. + */ + ctx.setSeqCode(seqCode); + + /* Number of connection attempts while sending the message via unix socket. + * Default value is 3 but you can change it. + */ + ctx.setConnAttempts(5); + + /* Timeout in seconds for the connection while sending the message via unix socket. + * Default value is 3 but you can change it. + */ + ctx.setTimeout(2); + + /* Path to directory where will be saved files with logs until inter-logger sends + * the content. + * Example: ctx.setPrefix("/home/paja6/tmp/dglog." + jobid.getUnique()); + */ + ctx.setPrefix(args[7]); + + /* Path to unix socket. + * Example: ctx.setPathToSocket("/home/paja6/tmp/il.sock"); + */ + ctx.setPathToSocket(args[8]); + + /* Create new instance of the event which will be logged. + */ + Running running = new Running(); + + /* Set some description for the event. + * Example: running.setNode("worker node"); + */ + running.setNode(args[9]); + + /* And now is the context and event prepared to work. + * + */ + ctx.log(running); + } + } +} diff --git a/org.glite.lb.client-java/src_c/Makefile b/org.glite.lb.client-java/src_c/Makefile new file mode 100755 index 0000000..4270cbf --- /dev/null +++ b/org.glite.lb.client-java/src_c/Makefile @@ -0,0 +1,18 @@ +CC=gcc +PREFIX=${HOME}/tmp +PATH_TO_JAVA=${JAVA_HOME} + +LIB=libglite_lb_sendviasocket.la +OBJ=send_via_socket.lo + +compile: ${LIB} + +${LIB}: ${OBJ} + libtool --mode=link ${CC} -rpath ${PREFIX}/lib -o $@ ${OBJ} + +%.lo: %.c + libtool --mode=compile ${CC} -I${PATH_TO_JAVA}/include -I${PATH_TO_JAVA}/include/linux -c $< + +install: compile + -mkdir -p ${PREFIX}/lib + libtool --mode=install install -m 755 ${LIB} ${PREFIX}/lib diff --git a/org.glite.lb.client-java/src_c/send_via_proxy.c b/org.glite.lb.client-java/src_c/send_via_proxy.c new file mode 100755 index 0000000..4894488 --- /dev/null +++ b/org.glite.lb.client-java/src_c/send_via_proxy.c @@ -0,0 +1,280 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + *---------------------------------------------------------------------- + * Open a GSS connection to local-logger, send already formatted ULM string + * and get answer back from local-logger + * \brief connect to local-logger, send message and get answer back + * \param[in,out] ctx context to work with, + * \param[in] logline formated ULM string + *---------------------------------------------------------------------- + */ +int edg_wll_DoLogEvent( + edg_wll_Context ctx, + edg_wll_LogLine logline) +{ + int ret = 0, answer = EAGAIN; + int conn; + + edg_wll_ResetError(ctx); + memset(&conn,0,sizeof(conn)); + + /* connect to local-logger */ + if ((ret = edg_wll_log_connect(ctx,&conn))) { + fprintf(stderr, "edg_wll_log_connect error"); + goto edg_wll_DoLogEvent_end; + } + + /* send message */ + if ((ret = edg_wll_log_write(ctx,conn,logline)) == -1) { + fprintf(stderr, "edg_wll_log_write error"); + goto edg_wll_DoLogEvent_end; + } + + /* get answer */ + if ((ret = edg_wll_log_read(ctx,conn)) == -1) { + fprintf(stderr, "edg_wll_log_read error"); + } else { + answer = edg_wll_Error(ctx, NULL, NULL); + } + +edg_wll_DoLogEvent_end: + if (ret) edg_wll_log_close(ctx,conn); + + return 0; +} + +/** + *---------------------------------------------------------------------- + * connect to locallogger + *---------------------------------------------------------------------- + */ +int edg_wll_log_connect(edg_wll_Context ctx, int *conn) +{ + int ret, answer=0, index; + char *my_subject_name = NULL; + edg_wll_GssStatus gss_stat; + + //edg_wll_ResetError(ctx); + //edg_wll_poolLock(); + + /* check if connection already in pool */ + if ( (index = ConnectionIndex(ctx, ctx->p_destination, ctx->p_dest_port)) == -1 ) { + if (ctx->connections->connOpened == ctx->connections->poolSize) + if (ReleaseConnection(ctx, NULL, 0)) + goto edg_wll_log_connect_end; + index = AddConnection(ctx, ctx->p_destination, ctx->p_dest_port); + if (index < 0) { + edg_wll_SetError(ctx,EAGAIN,"connection pool size exceeded"); + goto edg_wll_log_connect_end; + } +#if 0 + /* acquire gss credentials */ + ret = edg_wll_gss_acquire_cred_gsi( + ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_cert_filename, + ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_key_filename, + &ctx->connections->connPool[index].gsiCred, &my_subject_name, &gss_stat); + /* give up if unable to acquire prescribed credentials, otherwise go on anonymously */ + if (ret && ctx->p_proxy_filename) { + edg_wll_SetErrorGss(ctx, "edg_wll_gss_acquire_cred_gsi(): failed to load GSI credentials", &gss_stat); + goto edg_wll_log_connect_err; + } + /* gss_connect */ + if (ctx->connections->connPool[index].gss.context == GSS_C_NO_CONTEXT) { + + /* acquire gss credentials */ + ret = edg_wll_gss_acquire_cred_gsi( + ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_cert_filename, + ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_key_filename, + &ctx->connections->connPool[index].gsiCred, &my_subject_name, &gss_stat); + /* give up if unable to acquire prescribed credentials, otherwise go on anonymously */ + if (ret && ctx->p_proxy_filename) { + edg_wll_SetErrorGss(ctx, "edg_wll_gss_acquire_cred_gsi(): failed to load GSI credentials", &gss_stat); + goto edg_wll_log_connect_err; + } + if ((answer = edg_wll_gss_connect( + ctx->connections->connPool[index].gsiCred, + ctx->connections->connPool[index].peerName, + ctx->connections->connPool[index].peerPort, + &ctx->p_tmp_timeout, + &ctx->connections->connPool[index].gss, + &gss_stat)) < 0) { + answer = handle_gss_failures(ctx,answer,&gss_stat,"edg_wll_gss_connect()"); + goto edg_wll_log_connect_err; + } + goto edg_wll_log_connect_end; + } else goto edg_wll_log_connect_end; + +edg_wll_log_connect_err: + if (index >= 0) CloseConnection(ctx, &index); + index = -1; + +edg_wll_log_connect_end: + if (index >= 0) edg_wll_connectionTryLock(ctx, index); + if (my_subject_name) free(my_subject_name); + + edg_wll_poolUnlock(); + + *conn = index; + return answer; +} + +/** + *---------------------------------------------------------------------- + * close connection to locallogger + *---------------------------------------------------------------------- + */ +int edg_wll_log_close(edg_wll_Context ctx, int conn) +{ + int ret = 0; + + if (conn == -1) return 0; + ret = CloseConnection(ctx,&conn); + edg_wll_connectionUnlock(ctx,conn); + return ret; +} + +/** + *---------------------------------------------------------------------- + * write/send to locallogger + *---------------------------------------------------------------------- + */ +int edg_wll_log_write(edg_wll_Context ctx, int conn, edg_wll_LogLine logline) +{ + char header[EDG_WLL_LOG_SOCKET_HEADER_LENGTH+1]; + int err; + int answer; + size_t count,sent; + int size; + u_int8_t size_end[4]; + edg_wll_GssStatus gss_code; + + errno = err = answer = count = sent = 0; + size = strlen(logline)+1; + size_end[0] = size & 0xff; size >>= 8; + size_end[1] = size & 0xff; size >>= 8; + size_end[2] = size & 0xff; size >>= 8; + size_end[3] = size; + size = strlen(logline)+1; + + edg_wll_ResetError(ctx); + + sprintf(header,"%s",EDG_WLL_LOG_SOCKET_HEADER); + header[EDG_WLL_LOG_SOCKET_HEADER_LENGTH]='\0'; + if ((err = edg_wll_gss_write_full(&ctx->connections->connPool[conn].gss, header, EDG_WLL_LOG_SOCKET_HEADER_LENGTH, &ctx->p_tmp_timeout, &count, &gss_code)) < 0) { + switch (answer = handle_gss_failures(ctx,err,&gss_code,"edg_wll_gss_write_full()")) { + case ENOTCONN: + edg_wll_log_close(ctx,conn); + if (edg_wll_log_connect(ctx,&conn) || + edg_wll_gss_write_full(&ctx->connections->connPool[conn].gss, header, EDG_WLL_LOG_SOCKET_HEADER_LENGTH, &ctx->p_tmp_timeout, &count, &gss_code) < 0) { + edg_wll_UpdateError(ctx,answer,"edg_wll_log_write(): error sending header"); + return -1; + } + break; + case 0: + break; + default: + edg_wll_UpdateError(ctx,answer,"edg_wll_log_write(): error sending header"); + return -1; + } + } + sent += count; + + count = 0; + if ((err = edg_wll_gss_write_full(&ctx->connections->connPool[conn].gss, size_end, 4, &ctx->p_tmp_timeout, &count, &gss_code)) < 0) { + switch (answer = handle_gss_failures(ctx,err,&gss_code,"edg_wll_gss_write_full()")) { + case ENOTCONN: + edg_wll_log_close(ctx,conn); + if (edg_wll_log_connect(ctx,&conn) || + edg_wll_gss_write_full(&ctx->connections->connPool[conn].gss, size_end, 4, &ctx->p_tmp_timeout, &count, &gss_code) < 0) { + edg_wll_UpdateError(ctx,answer,"edg_wll_log_write(): error sending message size"); + return -1; + } + break; + case 0: + break; + default: + edg_wll_UpdateError(ctx,answer,"edg_wll_log_write(): error sending message size"); + return -1; + + } + } + sent += count; + + count = 0; + if (( err = edg_wll_gss_write_full(&ctx->connections->connPool[conn].gss, logline, size, &ctx->p_tmp_timeout, &count, &gss_code)) < 0) { + switch (answer = handle_gss_failures(ctx,err,&gss_code,"edg_wll_gss_write_full()")) { + case ENOTCONN: + edg_wll_log_close(ctx,conn); + if (edg_wll_log_connect(ctx,&conn) || + edg_wll_gss_write_full(&ctx->connections->connPool[conn].gss, logline, size, &ctx->p_tmp_timeout, &count, &gss_code) < 0) { + edg_wll_UpdateError(ctx,answer,"edg_wll_log_write(): error sending message"); + return -1; + } + break; + case 0: + break; + default: + edg_wll_UpdateError(ctx,answer,"edg_wll_log_write(): error sending message"); + return -1; + } + } + sent += count; + + return sent; +} + +/** + *---------------------------------------------------------------------- + * read/receive from locallogger + *---------------------------------------------------------------------- + */ +int edg_wll_log_read(edg_wll_Context ctx, int conn) +{ + int err; + int answer; + u_int8_t answer_end[4]; + size_t count; + edg_wll_GssStatus gss_code; + + errno = err = answer = count = 0; + + edg_wll_ResetError(ctx); + + count = 0; + if ((err = edg_wll_gss_read_full(&ctx->connections->connPool[conn].gss, answer_end, 4, &ctx->p_tmp_timeout, &count, &gss_code)) < 0 ) { + switch (answer = handle_gss_failures(ctx,err,&gss_code,"edg_wll_gss_read_full()")) { + case ENOTCONN: + edg_wll_log_close(ctx,conn); + if (edg_wll_log_connect(ctx,&conn) || + edg_wll_gss_read_full(&ctx->connections->connPool[conn].gss, answer_end, 4, &ctx->p_tmp_timeout, &count, &gss_code) < 0 ) { + edg_wll_UpdateError(ctx,answer,"edg_wll_log_read(): error reading answer from local-logger"); + return -1; + } + break; + case 0: + break; + default: + edg_wll_UpdateError(ctx,answer,"edg_wll_log_read(): error reading answer from local-logger"); + return -1; + } + } + answer = answer_end[3]; answer <<=8; + answer |= answer_end[2]; answer <<=8; + answer |= answer_end[1]; answer <<=8; + answer |= answer_end[0]; + edg_wll_SetError(ctx,answer,"edg_wll_log_read(): answer read from locallogger"); + + return count; +} diff --git a/org.glite.lb.client-java/src_c/send_via_socket.c b/org.glite.lb.client-java/src_c/send_via_socket.c new file mode 100755 index 0000000..4f0fc95 --- /dev/null +++ b/org.glite.lb.client-java/src_c/send_via_socket.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define tv_sub(a, b) {\ + (a).tv_usec -= (b).tv_usec;\ + (a).tv_sec -= (b).tv_sec;\ + if ((a).tv_usec < 0) {\ + (a).tv_sec--;\ + (a).tv_usec += 1000000;\ + }\ +} + + +/*! + * Write to socket + * Needn't write entire buffer. Timeout is applicable only for non-blocking + * connections + * \param sock IN: connection to work with + * \param buf IN: buffer + * \param bufsize IN: max size to write + * \param timeout INOUT: max time allowed for operation, remaining time on return + * \retval bytes written (>0) on success + * \retval -1 on write error + */ +static ssize_t +edg_wll_socket_write( + int sock, + const void *buf, + size_t bufsize, + struct timeval *timeout) +{ + ssize_t len = 0; + fd_set fds; + struct timeval to, before, after; + + + if ( timeout ) { + memcpy(&to, timeout, sizeof to); + gettimeofday(&before, NULL); + } + len = write(sock, buf, bufsize); + if ( len <= 0 && errno == EAGAIN ) { + FD_ZERO(&fds); + FD_SET(sock,&fds); + if ( select(sock+1, NULL, &fds, NULL, timeout? &to: NULL) < 0 ) { + len = -1; + } else { + len = write(sock, buf, bufsize); + } + } + if ( timeout ) { + gettimeofday(&after, NULL); + tv_sub(after, before); + tv_sub(*timeout, after); + if ( timeout->tv_sec < 0 ) { + timeout->tv_sec = 0; + timeout->tv_usec = 0; + } + } + + return len; +} + +/*! + * Write specified amount of data to socket + * Attempts to call edg_wll_socket_write() untill the entire request is satisfied + * (or times out). + * \param sock IN: connection to work with + * \param buf IN: buffer + * \param bufsize IN: max size to write + * \param timeout INOUT: max time allowed for operation, remaining time on return + * \param total OUT: bytes actually written + * \retval bytes written (>0) on success + * \retval -1 on write error + */ +static ssize_t +edg_wll_socket_write_full( + int sock, + void *buf, + size_t bufsize, + struct timeval *timeout, + ssize_t *total) +{ + ssize_t len; + *total = 0; + + while ( *total < bufsize ) { + len = edg_wll_socket_write(sock, buf+*total, bufsize-*total, timeout); + if (len < 0) return len; + *total += len; + } + + return 0; +} + +/* + * edg_wll_log_event_send - send event to the socket + * + * Returns: 0 if done properly or errno + * + */ +/*int edg_wll_log_event_send( + const char *socket_path, + long filepos, + const char *msg, + int msg_size, + int conn_attempts, + int timeout_int)*/ +/*JNIEXPORT jint JNICALL Java_org_glite_lb_ContextIL_edg_wll_log_event_send + (JNIEnv *env, + jobject jobj, + jstring socket_path_j, + jlong filepos_j, + jstring msg_j, + jint msg_size_j, + jint conn_attempts_j, + jint timeout_int_j)*/ +JNIEXPORT jint JNICALL Java_org_glite_lb_client_1java_ContextIL_sendToSocket + (JNIEnv *env, + jobject jobj, + jstring socket_path_j, + jlong filepos_j, + jstring msg_j, + jint msg_size_j, + jint conn_attempts_j, + jint timeout_int_j) + +{ + const char *socket_path = (*env)->GetStringUTFChars(env, socket_path_j, 0); + const char *msg = (*env)->GetStringUTFChars(env, msg_j, 0); + int timeout_int = (int) timeout_int_j; + //int timeout_int = 3; + long filepos = (long) filepos_j; + int msg_size = (int) msg_size_j; + int conn_attempts = (int) conn_attempts_j; + //int conn_attempts = 3; + struct timeval timeout; + timeout.tv_sec = timeout_int; + timeout.tv_usec = 0; + struct sockaddr_un saddr; + int msg_sock, + flags, + conn_timeout, i; + ssize_t count = 0; + + + if ( (msg_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) { + goto event_send_end; + } + + memset(&saddr, 0, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + strcpy(saddr.sun_path, socket_path); + + if ( (flags = fcntl(msg_sock, F_GETFL, 0)) < 0 + || fcntl(msg_sock, F_SETFL, flags | O_NONBLOCK) < 0 ) { + goto cleanup; + } + + conn_timeout = floor(timeout.tv_sec/(conn_attempts + 1)); + for ( i = 0; i < conn_attempts; i++) { + if ( connect(msg_sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0 ) { + if ( errno == EISCONN ) break; + else if ((errno == EAGAIN) || (errno == ETIMEDOUT)) { + sleep(conn_timeout); + timeout.tv_sec -= conn_timeout; + continue; + } else { + goto cleanup; + } + } else break; + } + + if ( edg_wll_socket_write_full(msg_sock, &filepos, sizeof(filepos), &timeout, &count) < 0 +) { + goto cleanup; + } + + if ( edg_wll_socket_write_full(msg_sock, (void *)msg, msg_size, +&timeout, &count) < 0 ) { + goto cleanup; + } + +cleanup: + close(msg_sock); + +event_send_end: + return 0; +}