зеркало из https://github.com/mozilla/pjs.git
Bug 106386 Correct misspellings in source code
patch by unknown@simplemachines.org r=timeless rs=brendan
This commit is contained in:
Родитель
f048013d47
Коммит
8049c182cd
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,150 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
// DebuggerChannel.h
|
||||
//
|
||||
// Scott M. Silver
|
||||
|
||||
// A simple minded communication stream for
|
||||
// the debugger pieces client/server
|
||||
|
||||
#ifndef _H_DEBUGGERCHANNEL
|
||||
#define _H_DEBUGGERCHANNEL
|
||||
|
||||
#include "prio.h"
|
||||
#include "prprf.h"
|
||||
#include "Fundamentals.h"
|
||||
#include "prlock.h"
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#ifdef XP_PC
|
||||
# include <wtypes.h>
|
||||
#endif
|
||||
|
||||
// FIX-ME endianness???
|
||||
struct DebuggerMessageRequest
|
||||
{
|
||||
Int32 request;
|
||||
};
|
||||
|
||||
struct DebuggerMessageResponse
|
||||
{
|
||||
Int32 status; // 0 = succesful, non-zero is an error code
|
||||
};
|
||||
|
||||
const Int32 kAddressToMethod = 120;
|
||||
const Int32 kMethodToAddress = 121;
|
||||
const Int32 kRequestNotifyMethodCompiledLoaded = 122;
|
||||
const Int32 kNotifyMethodCompiledLoaded = 123;
|
||||
const Int32 kRunClass = 124;
|
||||
const Int32 kNotifyOnClassLoad = 125;
|
||||
const Int32 kNotifyOnException = 126;
|
||||
const Int32 kRequestDebuggerThread = 127;
|
||||
|
||||
class NS_EXTERN DebuggerStream
|
||||
{
|
||||
PRFileDesc* mFileDesc;
|
||||
|
||||
public:
|
||||
DebuggerStream(PRFileDesc* inCommChannel) :
|
||||
mFileDesc(inCommChannel) { }
|
||||
DebuggerStream() :
|
||||
mFileDesc(0) { }
|
||||
|
||||
void writeRequest(Int32 inRequest);
|
||||
Int32 readRequest();
|
||||
void writeResponse(Int32 inStatus);
|
||||
Int32 readResponse();
|
||||
|
||||
Int32 readLength(); // actual binary int32
|
||||
|
||||
void writeString(const char* inString);
|
||||
char* readString(); // string must be deleted [] by callee
|
||||
|
||||
void* readPtr();
|
||||
void writePtr(const void* inPtr);
|
||||
|
||||
// r/w raw buffer dumping
|
||||
void writeDataRaw(const void* inData, Int32 inLength);
|
||||
void readDataRaw(void* outData, Int32 inLength);
|
||||
|
||||
// r/w length preceded data
|
||||
void writeData(const void* inData, Int32 inLength);
|
||||
void* readData();
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
void NS_EXTERN setDebuggerThreadID(DWORD inThreadID);
|
||||
DWORD NS_EXTERN getDebuggerThreadID();
|
||||
#define SET_DEBUGGER_THREAD_ID(inID) \
|
||||
PR_BEGIN_MACRO \
|
||||
setDebuggerThreadID(inID); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define SET_DEBUGGER_THREAD_ID(inID) \
|
||||
PR_BEGIN_MACRO \
|
||||
PR_END_MACRO
|
||||
#endif
|
||||
|
||||
const int kDebuggerPort = 8001;
|
||||
|
||||
typedef void (*NotifyCompileOrLoadedMethodHandler)(const char*, void*);
|
||||
|
||||
class NS_EXTERN DebuggerClientChannel
|
||||
{
|
||||
DebuggerStream mSync;
|
||||
DebuggerStream mAsync;
|
||||
NotifyCompileOrLoadedMethodHandler mCompLoadHandler;
|
||||
PRLock* mLock;
|
||||
|
||||
public:
|
||||
static DebuggerClientChannel* createClient();
|
||||
|
||||
char* requestAddressToMethod(const void* inAddress, Int32& outOffset);
|
||||
void* requestMethodToAddress(const char* inMethodName);
|
||||
void sendOneCharacterRequest(char inCharRequest);
|
||||
void* requestDebuggerThread();
|
||||
Int32 requestNotifyOnMethodCompileLoad(const char* inMethodName);
|
||||
Int32 requestRunClass(const char* inClassName);
|
||||
Int32 requestNotifyOnClassLoad(const char* inClassName);
|
||||
Int32 requestNotifyOnException(const char* inClassName);
|
||||
|
||||
void setCompileOrLoadMethodHandler(NotifyCompileOrLoadedMethodHandler inHandler) { mCompLoadHandler = inHandler; }
|
||||
|
||||
protected:
|
||||
DebuggerClientChannel(PRFileDesc* inSync, PRFileDesc* inAsync);
|
||||
|
||||
void handleCompileOrLoadedMethod(const char* inMethodName, void *inAddress)
|
||||
{
|
||||
if (mCompLoadHandler)
|
||||
(*mCompLoadHandler)(inMethodName, inAddress);
|
||||
}
|
||||
|
||||
bool waitForAsyncRequest();
|
||||
static void asyncRequestThread(void* inThisPtr);
|
||||
void handleAsyncRequest(Int32 inRequest);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,591 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "JavaVM.h"
|
||||
#include "Debugger.h"
|
||||
#include "jvmdi.h"
|
||||
#include "NativeCodeCache.h"
|
||||
#include "Thread.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
static JVMDI_EventHook eventHook;
|
||||
|
||||
/*
|
||||
* Return via "statusPtr" the status of the thread as one of
|
||||
* JVMDI_THREAD_STATUS_*.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_NULL_POINTER
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetThreadStatus(JNIEnv * /* env */, jthread thread, jint *statusPtr)
|
||||
{
|
||||
if (statusPtr == NULL) {
|
||||
return JVMDI_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
||||
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
|
||||
|
||||
*statusPtr = t->getStatus();
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Note: jvm.h has suspend/resume (which may be deprecated - as
|
||||
* Thread.suspend() has been). JVMDI version is different, as it
|
||||
* takes precautions to attempt to avoid deadlock. Also it
|
||||
* cannot be depreciated.
|
||||
*/
|
||||
/*
|
||||
* Suspend the specified thread.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_THREAD_SUSPENDED,
|
||||
* JVMDI_ERROR_VM_DEAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SuspendThread(JNIEnv * /*env*/, jthread thread)
|
||||
{
|
||||
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
||||
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
|
||||
|
||||
t->suspend();
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resume the specified thread.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_THREAD_NOT_SUSPENDED,
|
||||
* JVMDI_ERROR_VM_DEAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_ResumeThread(JNIEnv * /*env*/, jthread thread)
|
||||
{
|
||||
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
||||
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
|
||||
|
||||
t->resume();
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If shouldStep is true cause the thread to generate a
|
||||
* JVMDI_EVENT_SINGLE_STEP event with each byte-code executed.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD,
|
||||
* JVMDI_ERROR_THREAD_NOT_SUSPENDED (should suspension be a requirement?),
|
||||
* JVMDI_ERROR_VM_DEAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetSingleStep(JNIEnv * /*env*/, jthread thread, jboolean shouldStep)
|
||||
{
|
||||
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
||||
|
||||
jt->single_step = shouldStep;
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Thread Groups
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return in 'groupsPtr' an array of top-level thread groups (parentless
|
||||
* thread groups).
|
||||
* Note: array returned via 'groupsPtr' is allocated globally and must be
|
||||
* explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetTopThreadGroups(JNIEnv * /*env*/, jobjectArray * /*groupsPtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return in 'threadsPtr' an array of the threads within the specified
|
||||
* thread group.
|
||||
* Note: array returned via 'threadsPtr' is allocated globally and must be
|
||||
* explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetGroupsThreads(JNIEnv * /*env*/, jthreadGroup /*group*/,
|
||||
jobjectArray * /*threadsPtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return in 'groupsPtr' an array of the thread groups within the
|
||||
* specified thread group.
|
||||
* Note: array returned via 'groupsPtr' is allocated globally and must be
|
||||
* explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetGroupsThreadGroups(JNIEnv * /*env*/, jthreadGroup /*group*/,
|
||||
jobjectArray * /*groupsPtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Suspend all threads recursively contained in the thread group,
|
||||
* except the specified threads.
|
||||
* If except is NULL suspend all threads in group.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_INVALID_THREAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SuspendThreadGroup(JNIEnv * /*env*/, jthreadGroup /*group*/,
|
||||
jobjectArray /*except*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resume all threads (recursively) in the thread group, except the
|
||||
* specified threads. If except is NULL resume all threads in group.
|
||||
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_INVALID_THREAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_ResumeThreadGroup(JNIEnv * /*env*/, jthreadGroup /*group*/, jobjectArray /*except*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stack access
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return via "framePtr" the frame ID for the current stack frame
|
||||
* of this thread. Thread must be suspended. Only Java and
|
||||
* Java native frames are returned. FrameIDs become invalid if
|
||||
* the frame is resumed.
|
||||
* Errors: JVMDI_ERROR_NO_MORE_FRAMES, JVMDI_ERROR_INVALID_THREAD,
|
||||
* JVMDI_ERROR_THREAD_NOT_SUSPENDED, JVMDI_ERROR_NULL_POINTER
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetCurrentFrame(JNIEnv * /*env*/, jthread /*thread*/, jframeID* framePtr)
|
||||
{
|
||||
if (framePtr == NULL) {
|
||||
return JVMDI_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "framePtr" the frame ID for the stack frame that called
|
||||
* the specified frame. Only Java and Java native frames are returned.
|
||||
* Errors: JVMDI_ERROR_NO_MORE_FRAMES, JVMDI_ERROR_INVALID_FRAMEID,
|
||||
* JVMDI_ERROR_NULL_POINTER
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetCallerFrame(JNIEnv * /* env */, jframeID /* called*/, jframeID * /*framePtr*/)
|
||||
{
|
||||
// Use code from the stackwalker here
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "classPtr" and "methodPtr" the active method in the
|
||||
* specified frame.
|
||||
* Note: class returned via 'classPtr' is allocated globally and must be
|
||||
* explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_NULL_POINTER
|
||||
* JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetFrameMethod(JNIEnv * /*env*/, jframeID /*frame*/,
|
||||
jclass * /*classPtr*/, jmethodID * /*methodPtr*/)
|
||||
{
|
||||
// Use code from the stackwalker here
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "bciPtr" the byte-code index within the active method of
|
||||
* the specified frame. This is the index of the currently executing
|
||||
* instruction.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_NATIVE_FRAME,
|
||||
* JVMDI_ERROR_NULL_POINTER
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetFrameBCI(JNIEnv * /*env*/, jframeID /*frame*/, jint * /*bciPtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return via "valuePtr" the value of the local variable at the
|
||||
* specificied slot.
|
||||
* Note: object returned via 'valuePtr' is allocated globally and must be
|
||||
* explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_NATIVE_FRAME, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetLocalObject(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
||||
jobject * /*valuePtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "valuePtr" the value of the local variable at the
|
||||
* specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetLocalInt(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
||||
jint * /*valuePtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "valuePtr" the value of the local variable at the
|
||||
* specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetLocalLong(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
||||
jlong * /*valuePtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "valuePtr" the value of the local variable at the
|
||||
* specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetLocalFloat(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
||||
jfloat * /*valuePtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "valuePtr" the value of the local variable at the
|
||||
* specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
||||
* JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetLocalDouble(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
||||
jdouble * /*valuePtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the value of the local variable at the specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetLocalObject(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jobject /*value*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the value of the local variable at the specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetLocalInt(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jint /*value*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the value of the local variable at the specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetLocalLong(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jlong /*value*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the value of the local variable at the specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetLocalFloat(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jfloat /*value*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the value of the local variable at the specificied slot.
|
||||
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
||||
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetLocalDouble(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jdouble /*value*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Breakpoints
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set a breakpoint. Send a JVMDI_EVENT_BREAKPOINT event when the
|
||||
* instruction at the specified byte-code index in the specified
|
||||
* method is about to be executed.
|
||||
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
||||
* JVMDI_ERROR_INVALID_BCI, JVMDI_ERROR_DUPLICATE_BREAKPOINT,
|
||||
* JVMDI_ERROR_VM_DEAD, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetBreakpoint(JNIEnv * /*env*/, jclass /* clazz */,
|
||||
jmethodID method, jint /*bci*/)
|
||||
{
|
||||
CacheEntry* ce;
|
||||
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
||||
|
||||
if (ce == NULL) {
|
||||
/* either the method is not compiled - in which case compile it */
|
||||
return JVMDI_ERROR_INVALID_METHODID;
|
||||
}
|
||||
|
||||
void *code = addressFunction(ce->descriptor.method->getCode());
|
||||
|
||||
if (code == NULL) {
|
||||
return JVMDI_ERROR_INVALID_METHODID;
|
||||
} // else if (code == stub) compile and then break;
|
||||
|
||||
// Convert the bci to a pc offset and add it to code
|
||||
|
||||
VM::debugger.setBreakPoint(code);
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear a breakpoint.
|
||||
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
||||
* JVMDI_ERROR_INVALID_BCI, JVMDI_ERROR_NO_SUCH_BREAKPOINT,
|
||||
* JVMDI_ERROR_VM_DEAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_ClearBreakpoint(JNIEnv * /*env*/, jclass /*clazz*/, jmethodID /*method*/, jint /*bci*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear all breakpoints.
|
||||
* Errors: JVMDI_ERROR_VM_DEAD
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_ClearAllBreakpoints(JNIEnv * /*env*/)
|
||||
{
|
||||
VM::debugger.clearAllBreakPoints();
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the routine which will handle in-coming events.
|
||||
* Passing NULL as hook unsets hook.
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_SetEventHook(JNIEnv * /*env*/, JVMDI_EventHook hook)
|
||||
{
|
||||
eventHook = hook;
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Method access
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return via "namePtr" the method's name and via "signaturePtr" the
|
||||
* method's signature.
|
||||
* Note: strings returned via 'namePtr' and 'signaturePtr' are
|
||||
* allocated globally and must be explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
||||
* JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetMethodName(JNIEnv * env, jclass /*clazz*/, jmethodID method,
|
||||
jstring *namePtr, jstring *signaturePtr)
|
||||
{
|
||||
CacheEntry* ce;
|
||||
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
||||
|
||||
if (namePtr == NULL || signaturePtr == NULL) {
|
||||
return JVMDI_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (ce == NULL) {
|
||||
return JVMDI_ERROR_INVALID_METHODID;
|
||||
}
|
||||
|
||||
*namePtr = (jstring) env->NewGlobalRef(
|
||||
env->NewStringUTF(ce->descriptor.method->toString()));
|
||||
*signaturePtr = (jstring) env->NewGlobalRef(
|
||||
env->NewStringUTF(ce->descriptor.method->getSignatureString()));
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return via "definingClassPtr" the class in which this method is
|
||||
* defined.
|
||||
* Note: class returned via 'definingClassPtr' is allocated globally
|
||||
* and must be explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
||||
* JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetMethodDefiningClass(JNIEnv * env, jclass /* clazz */, jmethodID method,
|
||||
jclass * definingClassPtr)
|
||||
{
|
||||
CacheEntry* ce;
|
||||
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
||||
|
||||
if (definingClassPtr == NULL) {
|
||||
return JVMDI_ERROR_NULL_POINTER;
|
||||
}
|
||||
*definingClassPtr = (jclass) (env->NewGlobalRef((jobject)
|
||||
ce->descriptor.method->getDeclaringClass()));
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "isNativePtr" a boolean indicating whether the method
|
||||
* is native.
|
||||
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
||||
* JVMDI_ERROR_NULL_POINTER
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_IsMethodNative(JNIEnv * /* env */, jclass /* clazz */, jmethodID method,
|
||||
jboolean * isNativePtr)
|
||||
{
|
||||
if (isNativePtr == NULL) {
|
||||
return JVMDI_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
CacheEntry* ce;
|
||||
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
||||
|
||||
if (ce == NULL) {
|
||||
/* either the method is not compiled - in which case compile it */
|
||||
return JVMDI_ERROR_INVALID_METHODID;
|
||||
}
|
||||
|
||||
*isNativePtr = ce->descriptor.method->getMethodInfo().isNative();
|
||||
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return via "classesPtr" all classes currently loaded in the VM.
|
||||
* Note: array returned via 'classesPtr' is allocated globally
|
||||
* and must be explictly freed with DeleteGlobalRef.
|
||||
* Errors: JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetLoadedClasses(JNIEnv * /*env*/, jobjectArray * /*classesPtr*/)
|
||||
{
|
||||
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return via "versionPtr" the JVMDI version number.
|
||||
* Higher 16 bits is major version number, lower 16 bit is minor
|
||||
* version number.
|
||||
* Errors: JVMDI_ERROR_NULL_POINTER
|
||||
*/
|
||||
JNIEXPORT JNICALL(jvmdiError)
|
||||
JVMDI_GetVersionNumber(JNIEnv * /*env*/, jint *versionPtr)
|
||||
{
|
||||
if (versionPtr == NULL) {
|
||||
return JVMDI_ERROR_NULL_POINTER;
|
||||
}
|
||||
*versionPtr = 0x00000003;
|
||||
return JVMDI_ERROR_NONE;
|
||||
}
|
||||
|
||||
} // extern C
|
|
@ -1,56 +0,0 @@
|
|||
#!perl
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
use Cwd;
|
||||
|
||||
# Add our lib path to the Perl search path.
|
||||
use lib "../PerlLib/";
|
||||
use BuildMod;
|
||||
use TestsMod;
|
||||
use ReportMod;
|
||||
|
||||
while (1) {
|
||||
|
||||
# Build the Debug build.
|
||||
#@args = ("efDbg.txt");
|
||||
#$runTests = BuildMod::build(@args);
|
||||
|
||||
TestsMod::runSuite("testsuite.txt");
|
||||
|
||||
# Run the conformance tests only if the build was sucessful.
|
||||
if ($runTests) {
|
||||
|
||||
print "Tests not being run right now.\n";
|
||||
|
||||
# Temp way to run the tests.
|
||||
$save_dir = cwd;
|
||||
chdir("D:/continuousbuilds/tests");
|
||||
print ("running tests.\n");
|
||||
system("tcl D:/continuousbuilds/scripts/runTestSuite.tcl");
|
||||
chdir($save_dir);
|
||||
|
||||
}
|
||||
|
||||
# Build the Optimize build.
|
||||
#@args = ("efOpt.txt");
|
||||
#BuildMod::build(@args);
|
||||
|
||||
}
|
|
@ -1,260 +0,0 @@
|
|||
#!perl
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
package BuildMod;
|
||||
use Exporter;
|
||||
use Cwd;
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(checkArgs);
|
||||
|
||||
#
|
||||
# build
|
||||
#
|
||||
# Builds all modules specified in the build file.
|
||||
#
|
||||
sub build {
|
||||
|
||||
local @args = @_;
|
||||
|
||||
# Global variables.
|
||||
$buildFile = "";
|
||||
$buildTitle = "";
|
||||
$buildTarget = ""; # Dbg or Opt.
|
||||
$buildPlatform = ""; # WIN32, UNIX, WIN16...
|
||||
$buildName = ""; # $buildPlatform + $buildTarget
|
||||
|
||||
$buildLog = ""; # $buildPlatform + $buildTarget + "Log.txt";
|
||||
$buildStatus = 0; # Build flag.
|
||||
$buildStatusStr = "success";
|
||||
$startTime = "";
|
||||
|
||||
&parseArgs(@args);
|
||||
|
||||
# Open the build file.
|
||||
open BUILDFILE, $buildFile || die ("Cannot open build file.\n");
|
||||
|
||||
# Read in the build headers.
|
||||
$buildTitle = <BUILDFILE>;
|
||||
$buildPlatform = <BUILDFILE>;
|
||||
$buildTarget = <BUILDFILE>;
|
||||
|
||||
# Remove \n, if any,
|
||||
$buildTitle =~ s/\n$//;
|
||||
$buildPlatform =~ s/\n$//;
|
||||
$buildTarget =~ s/\n$//;
|
||||
|
||||
# Init variables.
|
||||
$buildName = "${buildPlatform} ${buildTarget}";
|
||||
$buildLog = "${buildPlatform}_${buildTarget}Log.txt";
|
||||
$startTime = time - 60 * 10;
|
||||
|
||||
# Inform Tinderbox that we are starting a build.
|
||||
&beginTinderbox;
|
||||
|
||||
# Open the build log.
|
||||
open(LOG, ">${buildLog}") || die "Cannot open build log.\n";
|
||||
|
||||
# Read from the build file and do build.
|
||||
while ($strBuf = <BUILDFILE>) {
|
||||
|
||||
#Remove any \n.
|
||||
$strBuf =~ s/\n//;
|
||||
|
||||
# Check if the command is to change to a directory.
|
||||
$loweredBuf = lc $strBuf;
|
||||
if ($loweredBuf =~ /^cd /) {
|
||||
|
||||
$dir = $strBuf;
|
||||
$dir =~ s/^cd\s+//;
|
||||
print "Changing to $dir\n";
|
||||
if (!chdir("$dir")) {
|
||||
print LOG "Cannot change to directory $dir\n";
|
||||
$buildStatus = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
print "$strBuf 2>&1 |\n";
|
||||
print LOG "$strBuf 2>&1 |\n";
|
||||
open(COMMAND,"$strBuf 2>&1 |");
|
||||
|
||||
# Tee the output
|
||||
while( <COMMAND> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(COMMAND);
|
||||
$buildStatus |= $?;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Check if the build is busted or sucessful.
|
||||
$buildStatusStr = ($buildStatus ? 'busted' : 'success');
|
||||
print("Build Status: $buildStatusStr\n");
|
||||
|
||||
# Finish the log file and send it to tinderbox.
|
||||
&endTinderbox(LOG);
|
||||
|
||||
# Rename the log file.
|
||||
rename("${buildLog}", "${buildPlatform}${buildTarget}.last");
|
||||
|
||||
# Return 1 if build was sucessful, else return 0;
|
||||
if ($buildStatusStr == 'success') {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# checkArgs
|
||||
#
|
||||
# Checks to see if there are command line arguments.
|
||||
# Returns true(1) or false(0).
|
||||
#
|
||||
sub checkArgs {
|
||||
|
||||
local @args = @_;
|
||||
|
||||
# print("Number of args: $#args\n");
|
||||
|
||||
if ($#args == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# parseArgs
|
||||
#
|
||||
# Go through the argument list and set the matching global
|
||||
# variables.
|
||||
#
|
||||
sub parseArgs {
|
||||
|
||||
local @args = @_;
|
||||
|
||||
# The first argument should the build file.
|
||||
$buildFile = $args[0];
|
||||
|
||||
# Check if the file exits.
|
||||
if (!(-e $buildFile)) {
|
||||
die "Build file does not exist in the current directory.\n";
|
||||
}
|
||||
|
||||
# Go through the rest of the arguments.
|
||||
print("Args: ");
|
||||
$i = 0;
|
||||
while( $i < @args ){
|
||||
|
||||
print("$args[$i]", "\n");
|
||||
|
||||
$i++;
|
||||
|
||||
# Ignore the rest of the arguments.
|
||||
|
||||
}
|
||||
print("\n");
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# beginTinderbox
|
||||
#
|
||||
# Sends mail to the Tinderbox daemon,
|
||||
# that a build is about to start.
|
||||
#
|
||||
sub beginTinderbox {
|
||||
|
||||
print "Telling Tinderbox that we are starting a build.\n";
|
||||
|
||||
open( LOG, ">>logfile" );
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $buildTitle\n";
|
||||
print LOG "tinderbox: builddate: $startTime\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $buildName\n";
|
||||
|
||||
if ($buildPlatform =~ /WIN32/) {
|
||||
print LOG "tinderbox: errorparser: windows\n";
|
||||
print LOG "tinderbox: buildfamily: windows\n";
|
||||
} else {
|
||||
|
||||
# ***** Need to add other platform specific info. *****
|
||||
print LOG "tinderbox: errorparser: unknown\n";
|
||||
print LOG "tinderbox: buildfamily: unknown\n";
|
||||
|
||||
}
|
||||
|
||||
print LOG "\n";
|
||||
close( LOG );
|
||||
|
||||
# Send the logfile to Tinderbox.
|
||||
if ($buildPlatform =~ /WIN32/) {
|
||||
print "Sending logfile.\n";
|
||||
system("$nstools\\bin\\blat logfile -t tinderbox-daemon\@warp" );
|
||||
} else {
|
||||
|
||||
# ***** Need to add other platform specific mailing methods. *****
|
||||
die "Don't know how to send on $buildPlatform\n";
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# endTinderbox
|
||||
#
|
||||
# Sends mail to the Tinderbox daemon,
|
||||
# that a build is done.
|
||||
#
|
||||
sub endTinderbox {
|
||||
|
||||
my($LOG) = @_;
|
||||
|
||||
print "Telling Tinderbox that the build is done.\n";
|
||||
print LOG "tinderbox: tree: $buildTitle\n";
|
||||
print LOG "tinderbox: builddate: $startTime\n";
|
||||
print LOG "tinderbox: status: $buildStatusStr\n";
|
||||
print LOG "tinderbox: build: $buildName\n";
|
||||
print LOG "tinderbox: errorparser: windows\n";
|
||||
print LOG "tinderbox: buildfamily: windows\n";
|
||||
|
||||
close LOG;
|
||||
|
||||
# Inform Tinderbox that the build is done.
|
||||
system("$nstools\\bin\\blat $buildLog -t tinderbox-daemon\@warp" );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
/* Test program for ClassFileSummary */
|
||||
|
||||
#include "prinit.h"
|
||||
#include "ClassFileSummary.h"
|
||||
#include "ClassCentral.h"
|
||||
#include "ErrorHandling.h"
|
||||
|
||||
char *fileName = 0;
|
||||
char *className = 0;
|
||||
char *classPath = 0;
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
printf("Usage: classinfo [-f filename] [-cpath classpath] classname\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void parseOptions(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (!strcmp(argv[i], "-f"))
|
||||
fileName = argv[++i];
|
||||
else if (!strcmp(argv[i], "-cpath"))
|
||||
classPath = argv[++i];
|
||||
else if (!strcmp(argv[i], "-help"))
|
||||
printUsage();
|
||||
else if (className) {/* must be a classname */
|
||||
printf("Syntax error or duplicate filename\n");
|
||||
printUsage();
|
||||
} else
|
||||
className = argv[i];
|
||||
|
||||
if (!className) {
|
||||
printf("Insufficient arguments\n");
|
||||
printUsage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Pool dynamicPool;
|
||||
ClassWorld world(dynamicPool);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifndef NO_NSPR
|
||||
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
#endif
|
||||
|
||||
parseOptions(argc, argv);
|
||||
|
||||
// Pool dynamicPool;
|
||||
StringPool sp(dynamicPool);
|
||||
// ClassWorld world(dynamicPool);
|
||||
|
||||
ClassCentral central(dynamicPool, world, sp, classPath);
|
||||
|
||||
printf("Initializing distinguished objects....\n");
|
||||
try {
|
||||
initDistinguishedObjects(central);
|
||||
} catch (VerifyError err) {
|
||||
printf("Error initializing distinguished objects: %d\n", err.cause);
|
||||
exit(1);
|
||||
}
|
||||
printf("Initialized distinguished objects!\n");
|
||||
|
||||
ClassFileSummary *info;
|
||||
const ConstantPool *constantPool;
|
||||
int constantPoolCount;
|
||||
|
||||
printf("Initialized class central\n");
|
||||
|
||||
try {
|
||||
if (fileName) {
|
||||
printf("Loading from file %s\n", fileName);
|
||||
info = ¢ral.addClass((const char *) className,
|
||||
(const char *) fileName);
|
||||
} else
|
||||
info = ¢ral.addClass((const char *) className);
|
||||
|
||||
} catch (VerifyError err) {
|
||||
printf("Cannot load class %s: error %d\n", className, err.cause);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
constantPool = info->getConstantPool();
|
||||
constantPoolCount = info->getConstantPoolCount();
|
||||
|
||||
printf("Total size of object : %d\n", info->getObjSize());
|
||||
|
||||
/* Resolve fields, methods, constants, interfaceMethods */
|
||||
for (i = 0; i < constantPoolCount; i++)
|
||||
if (constantPool->get(i)) {
|
||||
uint8 type = constantPool->get(i)->getType();
|
||||
|
||||
if (type == CR_CONSTANT_FIELDREF) {
|
||||
ConstantFieldRef *ref = (ConstantFieldRef *) constantPool->get(i);
|
||||
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
|
||||
ConstantClass *cclass = ref->getClassInfo();
|
||||
|
||||
printf("--> Resolving field %s::%s...\n",
|
||||
cclass->getUtf()->getUtfString(),
|
||||
nameAndType->getName()->getUtfString());
|
||||
|
||||
uint32 offset;
|
||||
bool isVolatile, isConstant;
|
||||
bool isStatic = false;
|
||||
TypeKind tk;
|
||||
ValueKind vk;
|
||||
|
||||
try {
|
||||
tk = info->lookupInstanceField(i, vk,
|
||||
offset, isVolatile, isConstant);
|
||||
} catch (VerifyError err) {
|
||||
printf("\tlookupInstanceField() failed with error %d.\n",
|
||||
err.cause);
|
||||
printf("\tOk, so it's not an instance field. Trying static.\n");
|
||||
addr a;
|
||||
|
||||
try {
|
||||
tk = info->lookupStaticField(i, vk, a, isVolatile, isConstant);
|
||||
isStatic = true;
|
||||
} catch (VerifyError err) {
|
||||
printf("Cannot resolve field %s: %d\n",
|
||||
nameAndType->getName()->getUtfString(), err.cause);
|
||||
}
|
||||
}
|
||||
|
||||
if (isStatic)
|
||||
printf("Resolved as static field.\n");
|
||||
else
|
||||
printf("Resolved as instance field with offset %u\n", offset);
|
||||
|
||||
} else if (type == CR_CONSTANT_METHODREF) {
|
||||
ConstantMethodRef *ref = (ConstantMethodRef *) constantPool->get(i);
|
||||
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
|
||||
ConstantClass *cclass = ref->getClassInfo();
|
||||
|
||||
const char *methodName = nameAndType->getName()->getUtfString();
|
||||
|
||||
printf("--> Resolving method %s::%s...\n",
|
||||
cclass->getUtf()->getUtfString(),
|
||||
methodName);
|
||||
|
||||
uint32 vIndex;
|
||||
addr a;
|
||||
Signature sig;
|
||||
bool dynamicallyResolved = false;
|
||||
|
||||
if (!strcmp(methodName, "<init>") || !strcmp(methodName, "<clinit>")) {
|
||||
try {
|
||||
info->lookupSpecialMethod(i, sig, a);
|
||||
|
||||
printf("\tResolved special method %s.\n", methodName);
|
||||
|
||||
} catch (VerifyError err) {
|
||||
printf("Could not resolve special method %s: error %d\n",
|
||||
methodName, err.cause);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
dynamicallyResolved =
|
||||
info->lookupVirtualMethod(i, sig, vIndex, a);
|
||||
} catch (VerifyError err) {
|
||||
printf("\tlookupVirtualMethod() failed with erorr %d\n",
|
||||
err.cause);
|
||||
printf("\tOk, so method is not virtual. trying static...\n");
|
||||
|
||||
try {
|
||||
info->lookupStaticMethod(i, sig, a);
|
||||
} catch (VerifyError err) {
|
||||
printf("Cannot resolve method %s: %d\n",
|
||||
nameAndType->getName()->getUtfString(), err.cause);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamicallyResolved)
|
||||
printf("\tResolved method %s as virtual: vindex %u.\n",
|
||||
nameAndType->getName()->getUtfString(), vIndex);
|
||||
else {
|
||||
printf("\tResolved method %s statically\n",
|
||||
nameAndType->getName()->getUtfString());
|
||||
}
|
||||
|
||||
} else if (type == CR_CONSTANT_INTERFACEMETHODREF) {
|
||||
ConstantMethodRef *ref = (ConstantMethodRef *) constantPool->get(i);
|
||||
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
|
||||
ConstantClass *cclass = ref->getClassInfo();
|
||||
|
||||
const char *methodName = nameAndType->getName()->getUtfString();
|
||||
printf("--> Resolving interface method %s::%s...\n",
|
||||
cclass->getUtf()->getUtfString(),
|
||||
methodName);
|
||||
|
||||
Signature sig;
|
||||
uint32 interfaceIndex;
|
||||
addr a;
|
||||
uint32 nArgs;
|
||||
|
||||
if (!strcmp(methodName, "<init>") || !strcmp(methodName, "<clinit>")) {
|
||||
try {
|
||||
info->lookupSpecialMethod(i, sig, a);
|
||||
|
||||
printf("\tResolved special method %s.\n", methodName);
|
||||
|
||||
} catch (VerifyError err) {
|
||||
printf("Could not resolve special method %s: error %d\n",
|
||||
methodName, err.cause);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
bool staticallyResolved = info->lookupInterfaceMethod(i, sig,
|
||||
interfaceIndex,
|
||||
a,
|
||||
nArgs);
|
||||
printf("\tResolved interface method %s %s.\n",
|
||||
nameAndType->getName()->getUtfString(),
|
||||
(staticallyResolved) ? "statically" : "dynamically");
|
||||
} catch (VerifyError err) {
|
||||
printf("\tCould not resolve interface method %s: error %d\n",
|
||||
nameAndType->getName()->getUtfString(), err.cause);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Successfully loaded class file. \n");
|
||||
|
||||
printf("Getting class descriptor...\n");
|
||||
Class *clazz = static_cast<Class *>(info->getThisClass());
|
||||
printf("Obtained class descriptor.\n");
|
||||
|
||||
/* Now look up all the interfaces this class implements */
|
||||
printf("Loading interfaces...\n");
|
||||
const Interface **interfaces = info->getInterfaces();
|
||||
|
||||
printf("Done!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_LAURENT
|
||||
#ifdef __GNUC__
|
||||
// for gcc with -fhandle-exceptions
|
||||
void terminate() {}
|
||||
#endif
|
||||
#endif
|
|
@ -1,273 +0,0 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
#ifndef _DEFLATE_H
|
||||
#define _DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2*L_CODES+1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s {
|
||||
union {
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union {
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef *pending_buf; /* output still pending */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
int pending; /* nb of bytes in the pending buffer */
|
||||
int noheader; /* suppress zlib header and adler32 */
|
||||
Byte data_type; /* UNKNOWN, BINARY or ASCII */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef *window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MSDOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf *prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf *head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
# define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS+1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2*L_CODES+1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
ulg compressed_len; /* total bit length of compressed file */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
|
||||
#ifdef DEBUG_ZIP
|
||||
ulg bits_sent; /* bit length of the compressed data */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
/* in trees.c */
|
||||
void _tr_init OF((deflate_state *s));
|
||||
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
void _tr_align OF((deflate_state *s));
|
||||
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
#endif
|
|
@ -1,521 +0,0 @@
|
|||
/* gzio.c -- IO on .gz files
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
#define Z_BUFSIZE 4096
|
||||
|
||||
#define ALLOC(size) malloc(size)
|
||||
#define TRYFREE(p) {if (p) free(p);}
|
||||
|
||||
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define RESERVED 0xE0 /* bits 5..7: reserved */
|
||||
|
||||
typedef struct gz_stream {
|
||||
z_stream stream;
|
||||
int z_err; /* error code for last stream operation */
|
||||
int z_eof; /* set if end of input file */
|
||||
FILE *file; /* .gz file */
|
||||
Byte *inbuf; /* input buffer */
|
||||
Byte *outbuf; /* output buffer */
|
||||
uLong crc; /* crc32 of uncompressed data */
|
||||
char *msg; /* error message */
|
||||
char *path; /* path name for debugging only */
|
||||
int transparent; /* 1 if input file is not a .gz file */
|
||||
char mode; /* 'w' or 'r' */
|
||||
} gz_stream;
|
||||
|
||||
|
||||
local gzFile gz_open OF((const char *path, const char *mode, int fd));
|
||||
local int get_byte OF((gz_stream *s));
|
||||
local void check_header OF((gz_stream *s));
|
||||
local int destroy OF((gz_stream *s));
|
||||
local void putLong OF((FILE *file, uLong x));
|
||||
local uLong getLong OF((gz_stream *s));
|
||||
|
||||
/* ===========================================================================
|
||||
Opens a gzip (.gz) file for reading or writing. The mode parameter
|
||||
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
|
||||
or path name (if fd == -1).
|
||||
gz_open return NULL if the file could not be opened or if there was
|
||||
insufficient memory to allocate the (de)compression state; errno
|
||||
can be checked to distinguish the two cases (if errno is zero, the
|
||||
zlib error is Z_MEM_ERROR).
|
||||
*/
|
||||
local gzFile gz_open (path, mode, fd)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
int fd;
|
||||
{
|
||||
int err;
|
||||
int level = Z_DEFAULT_COMPRESSION; /* compression level */
|
||||
char *p = (char*)mode;
|
||||
gz_stream *s;
|
||||
char fmode[80]; /* copy of mode, without the compression level */
|
||||
char *m = fmode;
|
||||
|
||||
if (!path || !mode) return Z_NULL;
|
||||
|
||||
s = (gz_stream *)ALLOC(sizeof(gz_stream));
|
||||
if (!s) return Z_NULL;
|
||||
|
||||
s->stream.zalloc = (alloc_func)0;
|
||||
s->stream.zfree = (free_func)0;
|
||||
s->stream.opaque = (voidpf)0;
|
||||
s->stream.next_in = s->inbuf = Z_NULL;
|
||||
s->stream.next_out = s->outbuf = Z_NULL;
|
||||
s->stream.avail_in = s->stream.avail_out = 0;
|
||||
s->file = NULL;
|
||||
s->z_err = Z_OK;
|
||||
s->z_eof = 0;
|
||||
s->crc = crc32(0L, Z_NULL, 0);
|
||||
s->msg = NULL;
|
||||
s->transparent = 0;
|
||||
|
||||
s->path = (char*)ALLOC(strlen(path)+1);
|
||||
if (s->path == NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
strcpy(s->path, path); /* do this early for debugging */
|
||||
|
||||
s->mode = '\0';
|
||||
do {
|
||||
if (*p == 'r') s->mode = 'r';
|
||||
if (*p == 'w' || *p == 'a') s->mode = 'w';
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
level = *p - '0';
|
||||
} else {
|
||||
*m++ = *p; /* copy the mode */
|
||||
}
|
||||
} while (*p++ && m != fmode + sizeof(fmode));
|
||||
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
|
||||
|
||||
if (s->mode == 'w') {
|
||||
err = deflateInit2(&(s->stream), level,
|
||||
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
|
||||
/* windowBits is passed < 0 to suppress zlib header */
|
||||
|
||||
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
|
||||
|
||||
if (err != Z_OK || s->outbuf == Z_NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
} else {
|
||||
err = inflateInit2(&(s->stream), -MAX_WBITS);
|
||||
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
|
||||
|
||||
if (err != Z_OK || s->inbuf == Z_NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
}
|
||||
s->stream.avail_out = Z_BUFSIZE;
|
||||
|
||||
errno = 0;
|
||||
s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
|
||||
|
||||
if (s->file == NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
if (s->mode == 'w') {
|
||||
/* Write a very simple .gz header:
|
||||
*/
|
||||
fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
|
||||
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
|
||||
} else {
|
||||
check_header(s); /* skip the .gz header */
|
||||
}
|
||||
return (gzFile)s;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Opens a gzip (.gz) file for reading or writing.
|
||||
*/
|
||||
gzFile gzopen (path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open (path, mode, -1);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
|
||||
to mimic the behavio(u)r of fdopen.
|
||||
*/
|
||||
gzFile gzdopen (fd, mode)
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
char name[20];
|
||||
|
||||
if (fd < 0) return (gzFile)Z_NULL;
|
||||
sprintf(name, "<fd:%d>", fd); /* for debugging */
|
||||
|
||||
return gz_open (name, mode, fd);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
|
||||
for end of file.
|
||||
IN assertion: the stream s has been sucessfully opened for reading.
|
||||
*/
|
||||
local int get_byte(s)
|
||||
gz_stream *s;
|
||||
{
|
||||
if (s->z_eof) return EOF;
|
||||
if (s->stream.avail_in == 0) {
|
||||
errno = 0;
|
||||
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
|
||||
if (s->stream.avail_in == 0) {
|
||||
s->z_eof = 1;
|
||||
if (ferror(s->file)) s->z_err = Z_ERRNO;
|
||||
return EOF;
|
||||
}
|
||||
s->stream.next_in = s->inbuf;
|
||||
}
|
||||
s->stream.avail_in--;
|
||||
return *(s->stream.next_in)++;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Check the gzip header of a gz_stream opened for reading. Set the stream
|
||||
mode to transparent if the gzip magic header is not present; set s->err
|
||||
to Z_DATA_ERROR if the magic header is present but the rest of the header
|
||||
is incorrect.
|
||||
IN assertion: the stream s has already been created sucessfully;
|
||||
s->stream.avail_in is zero for the first time, but may be non-zero
|
||||
for concatenated .gz files.
|
||||
*/
|
||||
local void check_header(s)
|
||||
gz_stream *s;
|
||||
{
|
||||
int method; /* method byte */
|
||||
int flags; /* flags byte */
|
||||
uInt len;
|
||||
int c;
|
||||
|
||||
/* Check the gzip magic header */
|
||||
for (len = 0; len < 2; len++) {
|
||||
c = get_byte(s);
|
||||
if (c != gz_magic[len]) {
|
||||
s->transparent = 1;
|
||||
if (c != EOF) s->stream.avail_in++, s->stream.next_in--;
|
||||
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
|
||||
return;
|
||||
}
|
||||
}
|
||||
method = get_byte(s);
|
||||
flags = get_byte(s);
|
||||
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
|
||||
s->z_err = Z_DATA_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Discard time, xflags and OS code: */
|
||||
for (len = 0; len < 6; len++) (void)get_byte(s);
|
||||
|
||||
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
|
||||
len = (uInt)get_byte(s);
|
||||
len += ((uInt)get_byte(s))<<8;
|
||||
/* len is garbage if EOF but the loop below will quit anyway */
|
||||
while (len-- != 0 && get_byte(s) != EOF) ;
|
||||
}
|
||||
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
|
||||
while ((c = get_byte(s)) != 0 && c != EOF) ;
|
||||
}
|
||||
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
|
||||
while ((c = get_byte(s)) != 0 && c != EOF) ;
|
||||
}
|
||||
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
|
||||
for (len = 0; len < 2; len++) (void)get_byte(s);
|
||||
}
|
||||
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Cleanup then free the given gz_stream. Return a zlib error code.
|
||||
Try freeing in the reverse order of allocations.
|
||||
*/
|
||||
local int destroy (s)
|
||||
gz_stream *s;
|
||||
{
|
||||
int err = Z_OK;
|
||||
|
||||
if (!s) return Z_STREAM_ERROR;
|
||||
|
||||
TRYFREE(s->msg);
|
||||
|
||||
if (s->stream.state != NULL) {
|
||||
if (s->mode == 'w') {
|
||||
err = deflateEnd(&(s->stream));
|
||||
} else if (s->mode == 'r') {
|
||||
err = inflateEnd(&(s->stream));
|
||||
}
|
||||
}
|
||||
if (s->file != NULL && fclose(s->file)) {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
if (s->z_err < 0) err = s->z_err;
|
||||
|
||||
TRYFREE(s->inbuf);
|
||||
TRYFREE(s->outbuf);
|
||||
TRYFREE(s->path);
|
||||
TRYFREE(s);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Reads the given number of uncompressed bytes from the compressed file.
|
||||
gzread returns the number of bytes actually read (0 for end of file).
|
||||
*/
|
||||
int gzread (file, buf, len)
|
||||
gzFile file;
|
||||
voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
Bytef *start = buf; /* starting point for crc computation */
|
||||
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
|
||||
|
||||
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
|
||||
|
||||
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
|
||||
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
|
||||
|
||||
s->stream.next_out = next_out = buf;
|
||||
s->stream.avail_out = len;
|
||||
|
||||
while (s->stream.avail_out != 0) {
|
||||
|
||||
if (s->transparent) {
|
||||
/* Copy first the lookahead bytes: */
|
||||
uInt n = s->stream.avail_in;
|
||||
if (n > s->stream.avail_out) n = s->stream.avail_out;
|
||||
if (n > 0) {
|
||||
zmemcpy(s->stream.next_out, s->stream.next_in, n);
|
||||
next_out += n;
|
||||
s->stream.next_out = next_out;
|
||||
s->stream.next_in += n;
|
||||
s->stream.avail_out -= n;
|
||||
s->stream.avail_in -= n;
|
||||
}
|
||||
if (s->stream.avail_out > 0) {
|
||||
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
|
||||
s->file);
|
||||
}
|
||||
return (int)(len - s->stream.avail_out);
|
||||
}
|
||||
if (s->stream.avail_in == 0 && !s->z_eof) {
|
||||
|
||||
errno = 0;
|
||||
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
|
||||
if (s->stream.avail_in == 0) {
|
||||
s->z_eof = 1;
|
||||
if (ferror(s->file)) {
|
||||
s->z_err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s->stream.next_in = s->inbuf;
|
||||
}
|
||||
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
|
||||
|
||||
if (s->z_err == Z_STREAM_END) {
|
||||
/* Check CRC and original size */
|
||||
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
|
||||
start = s->stream.next_out;
|
||||
|
||||
if (getLong(s) != s->crc || getLong(s) != s->stream.total_out) {
|
||||
s->z_err = Z_DATA_ERROR;
|
||||
} else {
|
||||
/* Check for concatenated .gz files: */
|
||||
check_header(s);
|
||||
if (s->z_err == Z_OK) {
|
||||
inflateReset(&(s->stream));
|
||||
s->crc = crc32(0L, Z_NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->z_err != Z_OK || s->z_eof) break;
|
||||
}
|
||||
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
|
||||
|
||||
return (int)(len - s->stream.avail_out);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Writes the given number of uncompressed bytes into the compressed file.
|
||||
gzwrite returns the number of bytes actually written (0 in case of error).
|
||||
*/
|
||||
int gzwrite (file, buf, len)
|
||||
gzFile file;
|
||||
const voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
|
||||
|
||||
s->stream.next_in = buf;
|
||||
s->stream.avail_in = len;
|
||||
|
||||
while (s->stream.avail_in != 0) {
|
||||
|
||||
if (s->stream.avail_out == 0) {
|
||||
|
||||
s->stream.next_out = s->outbuf;
|
||||
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
|
||||
s->z_err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
s->stream.avail_out = Z_BUFSIZE;
|
||||
}
|
||||
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
|
||||
if (s->z_err != Z_OK) break;
|
||||
}
|
||||
s->crc = crc32(s->crc, buf, len);
|
||||
|
||||
return (int)(len - s->stream.avail_in);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Flushes all pending output into the compressed file. The parameter
|
||||
flush is as in the deflate() function.
|
||||
gzflush should be called only when strictly necessary because it can
|
||||
degrade compression.
|
||||
*/
|
||||
int gzflush (file, flush)
|
||||
gzFile file;
|
||||
int flush;
|
||||
{
|
||||
uInt len;
|
||||
int done = 0;
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
|
||||
|
||||
s->stream.avail_in = 0; /* should be zero already anyway */
|
||||
|
||||
for (;;) {
|
||||
len = Z_BUFSIZE - s->stream.avail_out;
|
||||
|
||||
if (len != 0) {
|
||||
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
|
||||
s->z_err = Z_ERRNO;
|
||||
return Z_ERRNO;
|
||||
}
|
||||
s->stream.next_out = s->outbuf;
|
||||
s->stream.avail_out = Z_BUFSIZE;
|
||||
}
|
||||
if (done) break;
|
||||
s->z_err = deflate(&(s->stream), flush);
|
||||
|
||||
/* deflate has finished flushing only when it hasn't used up
|
||||
* all the available space in the output buffer:
|
||||
*/
|
||||
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
|
||||
|
||||
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
|
||||
}
|
||||
fflush(s->file);
|
||||
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Outputs a long in LSB order to the given file
|
||||
*/
|
||||
local void putLong (file, x)
|
||||
FILE *file;
|
||||
uLong x;
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < 4; n++) {
|
||||
fputc((int)(x & 0xff), file);
|
||||
x >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Reads a long in LSB order from the given gz_stream. Sets
|
||||
*/
|
||||
local uLong getLong (s)
|
||||
gz_stream *s;
|
||||
{
|
||||
uLong x = (uLong)get_byte(s);
|
||||
int c;
|
||||
|
||||
x += ((uLong)get_byte(s))<<8;
|
||||
x += ((uLong)get_byte(s))<<16;
|
||||
c = get_byte(s);
|
||||
if (c == EOF) s->z_err = Z_DATA_ERROR;
|
||||
x += ((uLong)c)<<24;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Flushes all pending output if necessary, closes the compressed file
|
||||
and deallocates all the (de)compression state.
|
||||
*/
|
||||
int gzclose (file)
|
||||
gzFile file;
|
||||
{
|
||||
int err;
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL) return Z_STREAM_ERROR;
|
||||
|
||||
if (s->mode == 'w') {
|
||||
err = gzflush (file, Z_FINISH);
|
||||
if (err != Z_OK) return destroy(file);
|
||||
|
||||
putLong (s->file, s->crc);
|
||||
putLong (s->file, s->stream.total_in);
|
||||
|
||||
}
|
||||
return destroy(file);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Returns the error message for the last error which occured on the
|
||||
given compressed file. errnum is set to zlib error number. If an
|
||||
error occured in the file system and not in the compression library,
|
||||
errnum is set to Z_ERRNO and the application may consult errno
|
||||
to get the exact error code.
|
||||
*/
|
||||
const char* gzerror (file, errnum)
|
||||
gzFile file;
|
||||
int *errnum;
|
||||
{
|
||||
char *m;
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL) {
|
||||
*errnum = Z_STREAM_ERROR;
|
||||
return (const char*)ERR_MSG(Z_STREAM_ERROR);
|
||||
}
|
||||
*errnum = s->z_err;
|
||||
if (*errnum == Z_OK) return (const char*)"";
|
||||
|
||||
m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
|
||||
|
||||
if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
|
||||
|
||||
TRYFREE(s->msg);
|
||||
s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
|
||||
strcpy(s->msg, s->path);
|
||||
strcat(s->msg, ": ");
|
||||
strcat(s->msg, m);
|
||||
return (const char*)s->msg;
|
||||
}
|
|
@ -1,727 +0,0 @@
|
|||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
#######################################################################
|
||||
### ###
|
||||
### R U L E S O F E N G A G E M E N T ###
|
||||
### ###
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
# Double-Colon rules for utilizing the binary release model. #
|
||||
#######################################################################
|
||||
|
||||
all:: export libs program install
|
||||
|
||||
autobuild:: export private_export libs program install
|
||||
|
||||
platform::
|
||||
@echo $(OBJDIR_NAME)
|
||||
|
||||
|
||||
#
|
||||
# IMPORTS will always be associated with a component. Therefore,
|
||||
# the "import" rule will always change directory to the top-level
|
||||
# of a component, and traverse the IMPORTS keyword from the
|
||||
# "manifest.mn" file located at this level only.
|
||||
#
|
||||
# note: if there is a trailing slash, the component will be appended
|
||||
# (see import.pl - only used for xpheader.jar)
|
||||
|
||||
import::
|
||||
@echo "== import.pl =="
|
||||
@perl -I$(DEPTH)/config/core $(DEPTH)/config/core/import.pl \
|
||||
"RELEASE_TREE=$(RELEASE_TREE)" \
|
||||
"IMPORTS=$(IMPORTS)" \
|
||||
"VERSION=$(VERSION)" \
|
||||
"OS_ARCH=$(OS_ARCH)" \
|
||||
"PLATFORM=$(PLATFORM)" \
|
||||
"SOURCE_RELEASE_PREFIX=$(SOURCE_RELEASE_XP_DIR)" \
|
||||
"SOURCE_MD_DIR=$(SOURCE_MD_DIR)" \
|
||||
"SOURCE_XP_DIR=$(XPDIST)" \
|
||||
"FILES=$(XPCLASS_JAR) $(XPHEADER_JAR) $(MDHEADER_JAR) $(MDBINARY_JAR)" \
|
||||
"$(XPCLASS_JAR)=$(RELEASE_XP_DIR)|$(SOURCE_CLASSES_DIR)" \
|
||||
"$(XPHEADER_JAR)=$(RELEASE_XP_DIR)|$(XPDIST)/public/" \
|
||||
"$(MDHEADER_JAR)=$(RELEASE_MD_DIR)|$(SOURCE_MD_DIR)/include" \
|
||||
"$(MDBINARY_JAR)=$(RELEASE_MD_DIR)|$(SOURCE_MD_DIR)"
|
||||
|
||||
# perl -I$(DEPTH)/config/core $(DEPTH)/config/core/import.pl \
|
||||
# "IMPORTS=$(IMPORTS)" \
|
||||
# "RELEASE_TREE=$(RELEASE_TREE)" \
|
||||
# "VERSION=$(VERSION)" \
|
||||
# "PLATFORM=$(PLATFORM)" \
|
||||
# "SOURCE_MD_DIR=$(SOURCE_MD_DIR)" \
|
||||
# "SOURCE_XP_DIR=$(XPDIST)" \
|
||||
# "OS_ARCH=$(OS_ARCH)" ;
|
||||
|
||||
|
||||
export::
|
||||
ifndef NO_EXPORT_IN_SUBDIRS
|
||||
+$(LOOP_OVER_DIRS)
|
||||
endif
|
||||
|
||||
private_export::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
release_export::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
libs :: $(TARGETS)
|
||||
ifndef NO_LIBS_IN_SUBDIRS
|
||||
+$(LOOP_OVER_DIRS)
|
||||
endif
|
||||
|
||||
program :: $(TARGETS)
|
||||
ifndef NO_PROGRAM_IN_SUBDIRS
|
||||
+$(LOOP_OVER_DIRS)
|
||||
endif
|
||||
|
||||
install:: $(TARGETS)
|
||||
ifdef LIBRARY
|
||||
$(INSTALL) -m 444 $(LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
ifdef SHARED_LIBRARY
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin
|
||||
endif
|
||||
ifdef IMPORT_LIBRARY
|
||||
$(INSTALL) -m 555 $(IMPORT_LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
ifdef PROGRAM
|
||||
$(INSTALL) -m 555 $(PROGRAM) $(DIST)/bin
|
||||
endif
|
||||
ifdef PROGRAMS
|
||||
$(INSTALL) -m 555 $(PROGRAMS) $(DIST)/bin
|
||||
endif
|
||||
ifndef NO_INSTALL_IN_SUBDIRS
|
||||
+$(LOOP_OVER_DIRS)
|
||||
endif
|
||||
|
||||
tests::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
clean clobber::
|
||||
rm -rf $(ALL_TRASH)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
realclean clobber_all::
|
||||
rm -rf $(wildcard *.OBJ) dist $(ALL_TRASH)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
#ifdef ALL_PLATFORMS
|
||||
#all_platforms:: $(NFSPWD)
|
||||
# @d=`$(NFSPWD)`; \
|
||||
# if test ! -d LOGS; then rm -rf LOGS; mkdir LOGS; fi; \
|
||||
# for h in $(PLATFORM_HOSTS); do \
|
||||
# echo "On $$h: $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log";\
|
||||
# rsh $$h -n "(chdir $$d; \
|
||||
# $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log; \
|
||||
# echo DONE) &" 2>&1 > LOGS/$$h.pid & \
|
||||
# sleep 1; \
|
||||
# done
|
||||
#
|
||||
#$(NFSPWD):
|
||||
# cd $(@D); $(MAKE) $(@F)
|
||||
#endif
|
||||
|
||||
#######################################################################
|
||||
# Double-Colon rules for populating the binary release model. #
|
||||
#######################################################################
|
||||
|
||||
|
||||
release_clean::
|
||||
rm -rf $(XPDIST)/release
|
||||
|
||||
release:: release_clean release_export release_md release_jars release_cpdistdir
|
||||
|
||||
release_cpdistdir::
|
||||
@echo "== cpdist.pl =="
|
||||
@perl -I$(DEPTH)/config/core $(DEPTH)/config/core/cpdist.pl \
|
||||
"RELEASE_TREE=$(RELEASE_TREE)" \
|
||||
"MODULE=${MODULE}" \
|
||||
"OS_ARCH=$(OS_ARCH)" \
|
||||
"RELEASE=$(RELEASE)" \
|
||||
"PLATFORM=$(PLATFORM)" \
|
||||
"RELEASE_VERSION=$(RELEASE_VERSION)" \
|
||||
"SOURCE_RELEASE_PREFIX=$(SOURCE_RELEASE_XP_DIR)" \
|
||||
"RELEASE_XP_DIR=$(RELEASE_XP_DIR)" \
|
||||
"RELEASE_MD_DIR=$(RELEASE_MD_DIR)" \
|
||||
"FILES=$(XPCLASS_JAR) $(XPHEADER_JAR) $(MDHEADER_JAR) $(MDBINARY_JAR) XP_FILES MD_FILES" \
|
||||
"$(XPCLASS_JAR)=$(SOURCE_RELEASE_CLASSES_DIR)|x"\
|
||||
"$(XPHEADER_JAR)=$(SOURCE_RELEASE_XPHEADERS_DIR)|x" \
|
||||
"$(MDHEADER_JAR)=$(SOURCE_RELEASE_MDHEADERS_DIR)|m" \
|
||||
"$(MDBINARY_JAR)=$(SOURCE_RELEASE_MD_DIR)|m" \
|
||||
"XP_FILES=$(XP_FILES)|xf" \
|
||||
"MD_FILES=$(MD_FILES)|mf"
|
||||
|
||||
|
||||
# Add $(SOURCE_RELEASE_XPSOURCE_JAR) to FILES line when ready
|
||||
|
||||
# $(SOURCE_RELEASE_xxx_JAR) is a name like yyy.jar
|
||||
# $(SOURCE_RELEASE_xx_DIR) is a name like
|
||||
|
||||
release_jars::
|
||||
@echo "== release.pl =="
|
||||
@perl -I$(DEPTH)/config/core $(DEPTH)/config/core/release.pl \
|
||||
"RELEASE_TREE=$(RELEASE_TREE)" \
|
||||
"PLATFORM=$(PLATFORM)" \
|
||||
"OS_ARCH=$(OS_ARCH)" \
|
||||
"RELEASE_VERSION=$(RELEASE_VERSION)" \
|
||||
"SOURCE_RELEASE_DIR=$(SOURCE_RELEASE_DIR)" \
|
||||
"FILES=$(XPCLASS_JAR) $(XPHEADER_JAR) $(MDHEADER_JAR) $(MDBINARY_JAR)" \
|
||||
"$(XPCLASS_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_CLASSES_DIR)|b"\
|
||||
"$(XPHEADER_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_XPHEADERS_DIR)|a" \
|
||||
"$(MDHEADER_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_MDHEADERS_DIR)|a" \
|
||||
"$(MDBINARY_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_MD_DIR)|bi"
|
||||
# "$(XPSOURCE_JAR)=$(SOURCE_RELEASE_PREFIX)|a"
|
||||
|
||||
|
||||
|
||||
release_md::
|
||||
ifdef LIBRARY
|
||||
$(INSTALL) -m 444 $(LIBRARY) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)
|
||||
endif
|
||||
ifdef SHARED_LIBRARY
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)
|
||||
endif
|
||||
ifdef IMPORT_LIBRARY
|
||||
$(INSTALL) -m 555 $(IMPORT_LIBRARY) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)
|
||||
endif
|
||||
ifdef PROGRAM
|
||||
$(INSTALL) -m 555 $(PROGRAM) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_BIN_DIR)
|
||||
endif
|
||||
ifdef PROGRAMS
|
||||
$(INSTALL) -m 555 $(PROGRAMS) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_BIN_DIR)
|
||||
endif
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
|
||||
alltags:
|
||||
rm -f TAGS
|
||||
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs etags -a
|
||||
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs ctags -a
|
||||
|
||||
$(PROGRAM): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(CC) $(OBJS) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else
|
||||
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(OS_LIBS)
|
||||
endif
|
||||
$(INSTALL) -m 555 $(PROGRAM) $(DIST)/bin
|
||||
|
||||
$(LIBRARY): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
$(AR) $(OBJS)
|
||||
$(RANLIB) $@
|
||||
$(INSTALL) -m 444 $(LIBRARY) $(DIST)/lib
|
||||
|
||||
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
|
||||
wlib +$(SHARED_LIBRARY)
|
||||
$(INSTALL) -m 555 $(IMPORT_LIBRARY) $(DIST)lib
|
||||
endif
|
||||
|
||||
$(SHARED_LIBRARY): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
echo "#!" > $(OBJDIR)/lib$(LIBRARY_NAME)_syms
|
||||
nm -B -C -g $(OBJS) \
|
||||
| awk '/ [T,D] / {print $$3}' \
|
||||
| sed -e 's/^\.//' \
|
||||
| sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms
|
||||
$(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \
|
||||
-bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
echo system windows dll initinstance >w16link
|
||||
echo option map >>w16link
|
||||
echo option oneautodata >>w16link
|
||||
echo option heapsize=32K >>w16link
|
||||
echo debug watcom all >>w16link
|
||||
echo name $@ >>w16link
|
||||
echo file >>w16link
|
||||
echo $(W16OBJS) >>w16link
|
||||
echo $(W16LIBS) >>w16link
|
||||
#echo extra: $(EXTRA_LIBS), os_libs: $(OS_LIBS), $(W16LIBS) >>w16link
|
||||
echo libfile libentry >>w16link
|
||||
$(LINK) @w16link.
|
||||
rm w16link
|
||||
else
|
||||
$(LINK_DLL) -MAP $(DLLBASE) $(OS_LIBS) $(EXTRA_LIBS) $(OBJS) $(LDFLAGS)
|
||||
endif
|
||||
$(INSTALL) -m 555 $(LIBRARY) $(DIST)/lib
|
||||
else
|
||||
$(MKSHLIB) -o $@ $(OBJS) $(LD_LIBS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
chmod +x $@
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin
|
||||
else
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
|
||||
$(PURE_LIBRARY):
|
||||
rm -f $@
|
||||
ifneq ($(OS_ARCH), WINNT)
|
||||
$(AR) $(OBJS)
|
||||
endif
|
||||
$(RANLIB) $@
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
$(RES): $(RESNAME)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(RC) -Fo$(RES) $(RESNAME)
|
||||
@echo $(RES) finished
|
||||
|
||||
$(DLL): $(OBJS) $(EXTRA_LIBS)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
$(LINK_DLL) $(OBJS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
endif
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)%$(PROG_SUFFIX): $(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(CC) $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else
|
||||
$(CC) -o $@ $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
ifdef HAVE_PURIFY
|
||||
$(OBJDIR)/$(PROG_PREFIX)%.pure: $(OBJDIR)/%$(OBJ_SUFFIX)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(PURIFY) $(CC) -Fo$@ -c $(CFLAGS) $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) $(PURELDFLAGS)
|
||||
else
|
||||
$(PURIFY) $(CC) -o $@ $(CFLAGS) $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) $(PURELDFLAGS)
|
||||
endif
|
||||
endif
|
||||
|
||||
WCCFLAGS1 := $(subst /,\\,$(CFLAGS))
|
||||
WCCFLAGS2 := $(subst -I,-i=,$(WCCFLAGS1))
|
||||
WCCFLAGS3 := $(subst -D,-d,$(WCCFLAGS2))
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
# $(DEPTH)/config/core/w16opt $(WCCFLAGS3)
|
||||
echo $(WCCFLAGS3) >w16wccf
|
||||
$(CC) -zq -fo$(OBJDIR)\\$(PROG_PREFIX)$*$(OBJ_SUFFIX) @w16wccf $*.c
|
||||
rm w16wccf
|
||||
else
|
||||
ifdef GENERATE_BROWSE_INFO
|
||||
@mkdir $(BROWSE_INFO_DIR)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $*.c -FR$(BROWSE_INFO_DIR)/$*.sbr
|
||||
else
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $*.c
|
||||
endif
|
||||
|
||||
endif
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) $*.c
|
||||
endif
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(AS) -o $@ $(ASFLAGS) -c $*.s
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.S
|
||||
@$(MAKE_OBJDIR)
|
||||
$(AS) -o $@ $(ASFLAGS) -c $*.S
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)%: %.cpp
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
$(CCC) -o $@ -c $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# Please keep the next two rules in sync.
|
||||
#
|
||||
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.cc
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCC) -o $@ -c $(CFLAGS) $*.cc
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.cpp
|
||||
@$(MAKE_OBJDIR)
|
||||
ifdef STRICT_CPLUSPLUS_SUFFIX
|
||||
echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > $(OBJDIR)/t_$*.cc
|
||||
$(CCC) -o $@ -c $(CFLAGS) $(OBJDIR)/t_$*.cc
|
||||
rm -f $(OBJDIR)/t_$*.cc
|
||||
else
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifdef GENERATE_BROWSE_INFO
|
||||
@mkdir $(BROWSE_INFO_DIR)
|
||||
$(CCC) -Fo$@ -c $(CFLAGS) $*.cpp -FR$(BROWSE_INFO_DIR)/$*.sbr
|
||||
else
|
||||
$(CCC) -Fo$@ -c $(CFLAGS) $*.cpp
|
||||
endif
|
||||
else
|
||||
$(CCC) -o $@ -c $(CFLAGS) $*.cpp
|
||||
endif
|
||||
endif #STRICT_CPLUSPLUS_SUFFIX
|
||||
|
||||
%.i: %.cpp
|
||||
$(CCC) -C -E $(CFLAGS) $< > $*.i
|
||||
|
||||
%.i: %.c
|
||||
$(CC) -C -E $(CFLAGS) $< > $*.i
|
||||
|
||||
$(OBJDIR)/%: %.pl
|
||||
rm -f $@; cp $*.pl $@; chmod +x $@
|
||||
|
||||
%: %.sh
|
||||
rm -f $@; cp $*.sh $@; chmod +x $@
|
||||
|
||||
ifdef DIRS
|
||||
$(DIRS)::
|
||||
@if test -d $@; then \
|
||||
set $(EXIT_ON_ERROR); \
|
||||
echo "cd $@; $(MAKE)"; \
|
||||
cd $@; $(MAKE); \
|
||||
set +e; \
|
||||
else \
|
||||
echo "Skipping non-directory $@..."; \
|
||||
fi; \
|
||||
$(CLICK_STOPWATCH)
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Bunch of things that extend the 'export' rule (in order):
|
||||
################################################################################
|
||||
|
||||
$(JAVA_DESTPATH) $(JAVA_DESTPATH)/$(PACKAGE) $(JMCSRCDIR)::
|
||||
@if test ! -d $@; then \
|
||||
echo Creating $@; \
|
||||
rm -rf $@; \
|
||||
$(NSINSTALL) -D $@; \
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
## IDL_GEN
|
||||
|
||||
ifneq ($(IDL_GEN),)
|
||||
|
||||
#export::
|
||||
# $(IDL2JAVA) $(IDL_GEN)
|
||||
|
||||
#all:: export
|
||||
|
||||
#clobber::
|
||||
# rm -f $(IDL_GEN:.idl=.class) # XXX wrong!
|
||||
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
### JSRCS -- for compiling java files
|
||||
|
||||
ifneq ($(JSRCS),)
|
||||
export:: $(JAVA_DESTPATH) $(JAVA_DESTPATH)/$(PACKAGE)
|
||||
@list=`perl $(DEPTH)/config/core/outofdate.pl $(PERLARG) \
|
||||
-d $(JAVA_DESTPATH)/$(PACKAGE) $(JSRCS)`; \
|
||||
if test "$$list"x != "x"; then \
|
||||
echo $(JAVAC) $$list; \
|
||||
$(JAVAC) $$list; \
|
||||
fi
|
||||
|
||||
all:: export
|
||||
|
||||
clobber::
|
||||
rm -f $(XPDIST)/classes/$(PACKAGE)/*.class
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# JDIRS -- like JSRCS, except you can give a list of directories and it will
|
||||
# compile all the out-of-date java files in those directories.
|
||||
#
|
||||
# NOTE: recursing through these can speed things up, but they also cause
|
||||
# some builds to run out of memory
|
||||
#
|
||||
ifdef JDIRS
|
||||
export:: $(JAVA_DESTPATH) $(JAVA_DESTPATH)/$(PACKAGE)
|
||||
@for d in $(JDIRS); do \
|
||||
if test -d $$d; then \
|
||||
set $(EXIT_ON_ERROR); \
|
||||
files=`echo $$d/*.java`; \
|
||||
list=`perl $(DEPTH)/config/core/outofdate.pl $(PERLARG) \
|
||||
-d $(JAVA_DESTPATH)/$(PACKAGE) $$files`; \
|
||||
if test "$${list}x" != "x"; thecoreconfn \
|
||||
echo Building all java files in $$d; \
|
||||
echo $(JAVAC) $$list; \
|
||||
$(JAVAC) $$list; \
|
||||
fi; \
|
||||
set +e; \
|
||||
else \
|
||||
echo "Skipping non-directory $$d..."; \
|
||||
fi; \
|
||||
$(CLICK_STOPWATCH); \
|
||||
done
|
||||
endif
|
||||
|
||||
#
|
||||
# JDK_GEN -- for generating "old style" native methods
|
||||
#
|
||||
# Generate JDK Headers and Stubs into the '_gen' and '_stubs' directory
|
||||
#
|
||||
ifneq ($(JDK_GEN),)
|
||||
ifdef NSBUILDROOT
|
||||
INCLUDES += -I$(JDK_GEN_DIR) -I$(XPDIST)
|
||||
else
|
||||
INCLUDES += -I$(JDK_GEN_DIR)
|
||||
endif
|
||||
JDK_PACKAGE_CLASSES := $(JDK_GEN)
|
||||
JDK_PATH_CLASSES := $(subst .,/,$(JDK_PACKAGE_CLASSES))
|
||||
JDK_HEADER_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JDK_PATH_CLASSES))
|
||||
JDK_STUB_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JDK_PATH_CLASSES))
|
||||
JDK_HEADER_CFILES := $(patsubst %,$(JDK_GEN_DIR)/%.h,$(JDK_GEN))
|
||||
JDK_STUB_CFILES := $(patsubst %,$(JDK_STUB_DIR)/%.c,$(JDK_GEN))
|
||||
|
||||
$(JDK_HEADER_CFILES): $(JDK_HEADER_CLASSFILES)
|
||||
$(JDK_STUB_CFILES): $(JDK_STUB_CLASSFILES)
|
||||
|
||||
export::
|
||||
@echo Generating/Updating JDK headers
|
||||
$(JAVAH) -d $(JDK_GEN_DIR) $(JDK_PACKAGE_CLASSES)
|
||||
@echo Generating/Updating JDK stubs
|
||||
$(JAVAH) -stubs -d $(JDK_STUB_DIR) $(JDK_PACKAGE_CLASSES)
|
||||
endif
|
||||
|
||||
#
|
||||
# JRI_GEN -- for generating JRI native methods
|
||||
#
|
||||
# Generate JRI Headers and Stubs into the 'jri' directory
|
||||
#
|
||||
ifneq ($(JRI_GEN),)
|
||||
ifdef NSBUILDROOT
|
||||
INCLUDES += -I$(JRI_GEN_DIR) -I$(XPDIST)
|
||||
else
|
||||
INCLUDES += -I$(JRI_GEN_DIR)
|
||||
endif
|
||||
JRI_PACKAGE_CLASSES := $(JRI_GEN)
|
||||
JRI_PATH_CLASSES := $(subst .,/,$(JRI_PACKAGE_CLASSES))
|
||||
JRI_HEADER_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JRI_PATH_CLASSES))
|
||||
JRI_STUB_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JRI_PATH_CLASSES))
|
||||
JRI_HEADER_CFILES := $(patsubst %,$(JRI_GEN_DIR)/%.h,$(JRI_GEN))
|
||||
JRI_STUB_CFILES := $(patsubst %,$(JRI_GEN_DIR)/%.c,$(JRI_GEN))
|
||||
|
||||
$(JRI_HEADER_CFILES): $(JRI_HEADER_CLASSFILES)
|
||||
$(JRI_STUB_CFILES): $(JRI_STUB_CLASSFILES)
|
||||
|
||||
export::
|
||||
@echo Generating/Updating JRI headers
|
||||
$(JAVAH) -jri -d $(JRI_GEN_DIR) $(JRI_PACKAGE_CLASSES)
|
||||
@echo Generating/Updating JRI stubs
|
||||
$(JAVAH) -jri -stubs -d $(JRI_GEN_DIR) $(JRI_PACKAGE_CLASSES)
|
||||
endif
|
||||
|
||||
#
|
||||
# JMC_EXPORT -- for declaring which java classes are to be exported for jmc
|
||||
#
|
||||
ifneq ($(JMC_EXPORT),)
|
||||
JMC_EXPORT_PATHS := $(subst .,/,$(JMC_EXPORT))
|
||||
JMC_EXPORT_FILES := $(patsubst %,$(JAVA_DESTPATH)/$(PACKAGE)/%.class,$(JMC_EXPORT_PATHS))
|
||||
|
||||
#
|
||||
# We're doing NSINSTALL -t here (copy mode) because calling INSTALL will pick up
|
||||
# your NSDISTMODE and make links relative to the current directory. This is a
|
||||
# problem because the source isn't in the current directory:
|
||||
#
|
||||
export:: $(JMC_EXPORT_FILES) $(JMCSRCDIR)
|
||||
$(NSINSTALL) -t -m 444 $(JMC_EXPORT_FILES) $(JMCSRCDIR)
|
||||
endif
|
||||
|
||||
#
|
||||
# JMC_GEN -- for generating java modules
|
||||
#
|
||||
# Provide default export & install rules when using JMC_GEN
|
||||
#
|
||||
ifneq ($(JMC_GEN),)
|
||||
INCLUDES += -I$(JMC_GEN_DIR) -I.
|
||||
JMC_HEADERS := $(patsubst %,$(JMC_GEN_DIR)/%.h,$(JMC_GEN))
|
||||
JMC_STUBS := $(patsubst %,$(JMC_GEN_DIR)/%.c,$(JMC_GEN))
|
||||
JMC_OBJS := $(patsubst %,$(OBJDIR)/%$(OBJ_SUFFIX),$(JMC_GEN))
|
||||
|
||||
$(JMC_GEN_DIR)/M%.h: $(JMCSRCDIR)/%.class
|
||||
$(JMC) -d $(JMC_GEN_DIR) -interface $(JMC_GEN_FLAGS) $(?F:.class=)
|
||||
|
||||
$(JMC_GEN_DIR)/M%.c: $(JMCSRCDIR)/%.class
|
||||
$(JMC) -d $(JMC_GEN_DIR) -module $(JMC_GEN_FLAGS) $(?F:.class=)
|
||||
|
||||
$(OBJDIR)/M%$(OBJ_SUFFIX): $(JMC_GEN_DIR)/M%.h $(JMC_GEN_DIR)/M%.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ -c $(CFLAGS) $(JMC_GEN_DIR)/M$*.c
|
||||
|
||||
export:: $(JMC_HEADERS) $(JMC_STUBS)
|
||||
endif
|
||||
|
||||
#
|
||||
# Copy each element of EXPORTS to $(XPDIST)/public/$(MODULE)/
|
||||
#
|
||||
ifneq ($(EXPORTS),)
|
||||
$(XPDIST)/public/$(MODULE)::
|
||||
@if test ! -d $@; then \
|
||||
echo Creating $@; \
|
||||
$(NSINSTALL) -D $@; \
|
||||
fi
|
||||
|
||||
export:: $(EXPORTS) $(XPDIST)/public/$(MODULE)
|
||||
$(INSTALL) -m 444 $(EXPORTS) $(XPDIST)/public/$(MODULE)
|
||||
endif
|
||||
|
||||
# Duplicate export rule for private exports, with different directories
|
||||
|
||||
ifneq ($(PRIVATE_EXPORTS),)
|
||||
$(XPDIST)/private/$(MODULE)::
|
||||
@if test ! -d $@; then \
|
||||
echo Creating $@; \
|
||||
$(NSINSTALL) -D $@; \
|
||||
fi
|
||||
|
||||
private_export:: $(PRIVATE_EXPORTS) $(XPDIST)/private/$(MODULE)
|
||||
$(INSTALL) -m 444 $(PRIVATE_EXPORTS) $(XPDIST)/private/$(MODULE)
|
||||
else
|
||||
private_export::
|
||||
endif
|
||||
|
||||
# Duplicate export rule for releases, with different directories
|
||||
|
||||
ifneq ($(EXPORTS),)
|
||||
$(XPDIST)/release/include::
|
||||
@if test ! -d $@; then \
|
||||
echo Creating $@; \
|
||||
$(NSINSTALL) -D $@; \
|
||||
fi
|
||||
|
||||
release_export:: $(EXPORTS) $(XPDIST)/release/include
|
||||
$(INSTALL) -m 444 $(EXPORTS) $(XPDIST)/release/include
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
ifneq ($(DEPENDENCIES),)
|
||||
-include $(DEPENDENCIES)
|
||||
endif
|
||||
|
||||
ifneq ($(OS_ARCH),WINNT)
|
||||
# Can't use sed because of its 4000-char line length limit, so resort to perl
|
||||
.DEFAULT:
|
||||
@perl -e ' \
|
||||
open(MD, "< $(DEPENDENCIES)"); \
|
||||
while (<MD>) { \
|
||||
if (m@ \.*/*$< @) { \
|
||||
$$found = 1; \
|
||||
last; \
|
||||
} \
|
||||
} \
|
||||
if ($$found) { \
|
||||
print "Removing stale dependency $< from $(DEPENDENCIES)\n"; \
|
||||
seek(MD, 0, 0); \
|
||||
$$tmpname = "$(OBJDIR)/fix.md" . $$$$; \
|
||||
open(TMD, "> " . $$tmpname); \
|
||||
while (<MD>) { \
|
||||
s@ \.*/*$< @ @; \
|
||||
if (!print TMD "$$_") { \
|
||||
unlink(($$tmpname)); \
|
||||
exit(1); \
|
||||
} \
|
||||
} \
|
||||
close(TMD); \
|
||||
if (!rename($$tmpname, "$(DEPENDENCIES)")) { \
|
||||
unlink(($$tmpname)); \
|
||||
} \
|
||||
} elsif ("$<" ne "$(DEPENDENCIES)") { \
|
||||
print "$(MAKE): *** No rule to make target $<. Stop.\n"; \
|
||||
exit(1); \
|
||||
}'
|
||||
endif
|
||||
|
||||
#############################################################################
|
||||
# X dependency system
|
||||
#############################################################################
|
||||
|
||||
$(MKDEPENDENCIES): $(CSRCS) $(CPPSRCS) $(ASFILES) Makefile \
|
||||
$(EXPORTS) $(LOCAL_EXPORTS)
|
||||
@$(MAKE_OBJDIR)
|
||||
touch $(MKDEPENDENCIES)
|
||||
$(MKDEPEND) -p$(OBJDIR_NAME)/ -o'$(OBJ_SUFFIX)' -f$(MKDEPENDENCIES) $(INCLUDES) $(SYS_INCLUDES) $(CSRCS) $(CPPSRCS) $(ASFILES)
|
||||
|
||||
$(MKDEPEND):
|
||||
cd $(MKDEPEND_DIR); $(MAKE)
|
||||
|
||||
ifdef OBJS
|
||||
depend:: $(MKDEPEND) $(MKDEPENDENCIES)
|
||||
else
|
||||
depend::
|
||||
endif
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
dependclean::
|
||||
rm -f $(MKDEPENDENCIES)
|
||||
+$(LOOP_OVER_DIR)
|
||||
|
||||
# CUR_DIR is neccesary since it seems to crash gmake otherwise
|
||||
CUR_DIR = $(shell pwd)
|
||||
|
||||
ifndef NO_IMPLICIT_DEPENDENCIES
|
||||
|
||||
ifdef OBJS
|
||||
libs:: $(MKDEPENDENCIES)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifneq ($(wildcard $(CUR_DIR)/$(OBJDIR)/depend.mk),)
|
||||
-include $(CUR_DIR)/$(OBJDIR)/depend.mk
|
||||
endif
|
||||
|
||||
|
||||
################################################################################
|
||||
# Special gmake rules.
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Re-define the list of default suffixes, so gmake won't have to churn through
|
||||
# hundreds of built-in suffix rules for stuff we don't need.
|
||||
#
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .out .a .ln .o .obj .c .cc .C .cpp .y .l .s .S .h .sh .i .pl .class .java .html
|
||||
|
||||
#
|
||||
# Don't delete these files if we get killed.
|
||||
#
|
||||
.PRECIOUS: .java $(JDK_HEADERS) $(JDK_STUBS) $(JRI_HEADERS) $(JRI_STUBS) $(JMC_HEADERS) $(JMC_STUBS)
|
||||
|
||||
#
|
||||
# Fake targets. Always run these rules, even if a file/directory with that
|
||||
# name already exists.
|
||||
#
|
||||
.PHONY: all all_platforms alltags boot clean clobber clobber_all export install libs realclean release $(OBJDIR) $(DIRS)
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
include $(DEPTH)/config/ruleset.mk
|
||||
|
||||
# Set TARGETS to null so that the config/corerules work
|
||||
#TARGETS =
|
||||
|
||||
# This is actually our modified version of
|
||||
# $(DEPTH)/config/core/rules.mk, and should
|
||||
# hopefully be temporary until we can get the
|
||||
# config/core people to merge our changes with theirs
|
||||
include $(DEPTH)/config/corerules.mk
|
||||
|
||||
ifneq ($(MODULE_NAME),)
|
||||
|
||||
# OBJFILTERS is neccesary for the ifneq check below
|
||||
# since OBJS seems to have an undetermined number of blanks in it
|
||||
OBJFILTERS = $(filter %$(OBJ_SUFFIX),$(OBJS))
|
||||
|
||||
ifneq ($(OBJFILTERS),)
|
||||
MODULE_FILE = $(OBJDIR)/moduleFile
|
||||
$(MODULE_FILE): $(OBJS)
|
||||
@$(MKDIR) $(DIST)/modules/$(MODULE_NAME)
|
||||
@$(MAKE_OBJDIR)
|
||||
cp -f $? $(DIST)/modules/$(MODULE_NAME)
|
||||
touch $(MODULE_FILE)
|
||||
|
||||
libs:: $(MODULE_FILE)
|
||||
|
||||
clean::
|
||||
rm -f $(MODULE_FILE)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(HEADER_GEN),)
|
||||
$(HEADER_INCLUDES):
|
||||
@$(MKDIR) $(HEADER_GEN_DIR)
|
||||
$(JAVAH) -d $(HEADER_GEN_DIR) $(HEADER_GEN)
|
||||
|
||||
$(OBJS) : $(HEADER_INCLUDES)
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(filter %.h,$(LOCAL_EXPORTS)),)
|
||||
LOCAL_EXPORT_FILES = $(addprefix $(LOCAL_EXPORT_DIR)/,$(LOCAL_EXPORTS))
|
||||
|
||||
$(LOCAL_EXPORT_DIR)/%.h : %.h
|
||||
@$(MKDIR) $(LOCAL_EXPORT_DIR)
|
||||
@rm -f $(LOCAL_EXPORT_DIR)/$<
|
||||
$(LN) $(CUR_DIR)/$< $(LOCAL_EXPORT_DIR)/$<
|
||||
|
||||
export:: $(LOCAL_EXPORT_FILES)
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_x86)),)
|
||||
LOCAL_MD_x86_EXPORT_FILES = $(addprefix $(LOCAL_EXPORT_DIR)/md/x86/,$(LOCAL_MD_EXPORTS_x86))
|
||||
|
||||
$(LOCAL_EXPORT_DIR)/md/x86/%.h : %.h
|
||||
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/x86
|
||||
@rm -f $(LOCAL_EXPORT_DIR)/md/x86/$<
|
||||
$(LN) $(CUR_DIR)/$< $(LOCAL_EXPORT_DIR)/md/x86/$<
|
||||
|
||||
export:: $(LOCAL_MD_x86_EXPORT_FILES)
|
||||
endif
|
||||
|
||||
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_ppc)),)
|
||||
export::
|
||||
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/ppc
|
||||
@$(LN) $(LOCAL_MD_EXPORTS_ppc) $(LOCAL_EXPORT_DIR)/md/ppc
|
||||
endif
|
||||
|
||||
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_sparc)),)
|
||||
export::
|
||||
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/sparc
|
||||
@$(LN) $(LOCAL_MD_EXPORTS_sparc) $(LOCAL_EXPORT_DIR)/md/sparc
|
||||
endif
|
||||
|
||||
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_hppa)),)
|
||||
export::
|
||||
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/hppa
|
||||
@$(LN) $(LOCAL_MD_EXPORTS_hppa) $(LOCAL_EXPORT_DIR)/md/hppa/$<
|
||||
endif
|
||||
|
||||
# Browse information
|
||||
$(BROWSE_INFO_FILE): $(BROWSE_INFO_OBJS)
|
||||
$(BROWSE_INFO_PROGRAM) $(BROWSE_INFO_FLAGS) -o $(BROWSE_INFO_FILE) $(BROWSE_INFO_OBJS)
|
||||
@cp $(BROWSE_INFO_FILE) $(DIST)/lib
|
||||
|
||||
# Remove additional ef-specific junk
|
||||
clean::
|
||||
rm -f $(OBJDIR)/vc50*.*
|
||||
rm -f $(OBJDIR)/BrowseInfo/*.sbr
|
||||
|
||||
clobber::
|
||||
rm -r -f $(OBJDIR)/BrowseInfo
|
||||
|
||||
ifneq ($(LIBRARIES),)
|
||||
|
||||
# Add the lib prefix on all platforms except WINNT
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
LIBRARIES := $(addprefix $(DIST)/lib/,$(LIBRARIES))
|
||||
LIBRARIES := $(addsuffix .lib,$(LIBRARIES))
|
||||
else
|
||||
LIBRARIES := $(addprefix -l,$(LIBRARIES))
|
||||
endif
|
||||
|
||||
LDFLAGS += $(LIBRARIES)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
MailStone 4.15: Changes to Mailstone since version 4.1
|
||||
|
||||
* Setup now checks license acceptance and configures a basic
|
||||
setup. By default, it will also create a user LDIF file with a
|
||||
'allusers' account.
|
||||
|
||||
* All parameters and and testbed information may now be specified
|
||||
in the workload files (*.wld). New sections: CONFIG, CLIENT,
|
||||
MONITOR, PRETEST, and POSTTEST. Command line parameters still
|
||||
override the files. A complete copy of the configuration is saved
|
||||
in results/<TIMESTAMP>/all.wld.
|
||||
|
||||
* The '*.pl', '*.tbd', and 'config*' files in ./conf/ are
|
||||
depreciated. These should still work, but the new sections are
|
||||
simpler and more flexible.
|
||||
|
||||
* Any CONFIG parameter can now be specified on the command line
|
||||
using the form: 'PARAMETER=value'. Note that PARAMETER is case
|
||||
insensitive. No whitespace is allowed before or after the '='.
|
||||
|
||||
* The new switch '-l' or CONFIG parameter 'ClientCount' can now
|
||||
specify the total number of clients. The 'MaxClients' and
|
||||
'MaxThreads' parameters in each CLIENT section control load
|
||||
balancing. If the 'processes' and 'threads' parameters are set,
|
||||
then the load for that CLIENT section will not be adjusted, but
|
||||
will be taken into account when calculating other CLIENT sections.
|
||||
If just 'processes' is set, then only the thread count will be
|
||||
adjusted. All hosts in a CLIENT section will run the same number
|
||||
of processes and threads.
|
||||
|
||||
* bin/makeusers.pl now creates users, broadcast account, etc.
|
||||
Numbered passwords are now suppored. The new user/password format
|
||||
now replaces '%ld' with the user number to match the rest of
|
||||
mailstone. The ldif/ directory is obsolete. Run "perl/bin/perl
|
||||
bin/makeusers.pl -h" for usage.
|
||||
|
||||
* NT client machines may now be used from a Unix test master. See
|
||||
conf/sample.wld for configuration details.
|
||||
|
||||
* Commands can now be run for a specified block count, error
|
||||
count, or time (whichever comes first). Set 'maxBlocks' and/or
|
||||
'maxErrors'.
|
||||
|
||||
* Telemetry logging to /var/tmp/mstone-log.pn.tn is now performed
|
||||
when "telemetry 1" is specified.
|
||||
|
||||
* The name used in the "CLIENT" section is now used to match
|
||||
"HOSTS=..." qualifier. Compatibility with "hostname" is no longer
|
||||
needed.
|
||||
|
||||
* Config values can now use quoted characters such as \n, \r, \t
|
||||
|
||||
* Config values can be continued using \ (backslash)
|
||||
|
||||
* System configuration information (SYSCONFIG) can now be
|
||||
specified entirely within a workload file by quoting the newlines.
|
||||
|
||||
* Config values get enclosing double-quotes stripped
|
||||
|
||||
* Preliminary support for HTTP and WMAP (WebMail) testing.
|
||||
|
||||
* New table formats are easier to interpret and allow more protocols.
|
||||
|
||||
* The new text format report is easier to machine processes.
|
||||
|
||||
* The following command line switches are now obsolete: -f, -g,
|
||||
-e, -p, and -l. The same functionality can be obtained by
|
||||
FREQUENCY=<interval>, GNUPLOT=<path>, RSH=<path>, RCP=<path>, and
|
||||
TEMPDIR=<directory> respectively.
|
||||
|
||||
* File backups are now created. When ./process is run multiple
|
||||
times, the old files are moved to the ./tmp/<TIMESTAMP>/
|
||||
directory.
|
||||
|
||||
* perl has been updated to include full perl5.005_03 install
|
||||
package. Perl support for each architecture is now under the
|
||||
perl/ directory.
|
222
mstone/INSTALL
222
mstone/INSTALL
|
@ -1,222 +0,0 @@
|
|||
|
||||
Mstone 4.15 Quick Installation
|
||||
|
||||
This version of Mstone runs on many current UNIX platforms and NT.
|
||||
Only a web browser and text editor are needed to view the results and
|
||||
configure tests.
|
||||
|
||||
|
||||
QUICK INSTALL
|
||||
-------------
|
||||
|
||||
IMPORTANT: If you have an existing mstone, save a copy of the
|
||||
mstone/conf directory to preserve any configuration files you may want
|
||||
to keep.
|
||||
|
||||
Unpack distribution:
|
||||
|
||||
tar xzf /tmp/mstone_OPT.tar.gz
|
||||
or
|
||||
gunzip -c /tmp/mstone_OPT.tar.gz | tar xf -
|
||||
or
|
||||
unzip /tmp/mstone_OPT.zip
|
||||
|
||||
cd mstone
|
||||
|
||||
Both the tar.gz file and the zip file are identical. Use whichever is
|
||||
more convenient for you.
|
||||
|
||||
This will create a sub-directory named "mstone" with files and
|
||||
directories under that.
|
||||
|
||||
cd mstone
|
||||
|
||||
NOTE: all scripts must be run from the mstone directory.
|
||||
|
||||
|
||||
Do initial configuration:
|
||||
|
||||
Run "mstone config". It will ask you about your system configuration.
|
||||
Fill in the appropriate values and create the optional user accounts
|
||||
and broadcast account. When it asks about client machines, enter them
|
||||
seperated by commas, with no spaces (e.g. host1,host2,host3). If you
|
||||
need to re-configure, run "mstone config".
|
||||
|
||||
The machine starting the test may also be a client. For accurate
|
||||
results, clients should not be run on the test mailserver machine (or
|
||||
its directory server). If all the client machines are not running
|
||||
the same operating system version, see "Configuring Client Machines"
|
||||
below to configure for different OSes.
|
||||
|
||||
When the test master is on NT, only the local machine may be a client
|
||||
and only one process is allowed. You will not be asked about client
|
||||
machines.
|
||||
|
||||
Setup only configures the most important parameters. If you have more
|
||||
advanced needs, edit conf/general.wld appropriately.
|
||||
|
||||
Run "mstone setup". It will now push the necessary files to each
|
||||
client machine. If there are problems (i.e. with rsh permissions),
|
||||
fix them and re-run "mstone setup" until everything works.
|
||||
|
||||
|
||||
Install test accounts:
|
||||
|
||||
Setup will create a file called conf/MAILHOST.ldif (where MAILHOST is the
|
||||
name of your mail server). If you are not using Netscape Messaging
|
||||
and Directory Servers, then you may have to edit the ldif file or use
|
||||
alternate means to create the user accounts.
|
||||
|
||||
To import these users into Netscape Messaging Server, use "add
|
||||
entries" from the directory console or use the ldapmodify command line
|
||||
utility.
|
||||
|
||||
Note: imports will go faster if access logging is disabled. For large
|
||||
user counts (more than 10,000 users), it may be much faster to export
|
||||
the current database, merge the files together manually, and then
|
||||
import the new database.
|
||||
|
||||
Here is how the ldapmodify supplied with Netscape Messaging Server
|
||||
would be used.
|
||||
|
||||
setenv LD_LIBRARY_PATH /usr/netscape/messaging/lib
|
||||
cd /usr/netscape/messaging
|
||||
shared/bin/ldapmodify -h mailhost -a -D 'cn=directory manager' -w d_m_password < conf/MAILHOST.ldif
|
||||
|
||||
|
||||
Check time consistency:
|
||||
|
||||
IMPORTANT: The system time on each client machine must be synchronized
|
||||
within one second of each other for accurate results graphs.
|
||||
|
||||
Run "checktime" to see the time on each client. There should not be
|
||||
more than two seconds difference among the displayed time.
|
||||
|
||||
The best way to synchronize clients is use NTP (Network Time Protocol)
|
||||
or similar protocols (like rdate or timeslave) that have sub second
|
||||
accuracy.
|
||||
|
||||
A simple utility called "timesync" is provide to push the local
|
||||
system time to all clients. You must be root and have root rsh
|
||||
permissions to use timesync. Timesync only works on OSs that support
|
||||
setting seconds using "date MMDDhhmmCCYY.ss". Timesync is only
|
||||
accurate to a second (at best) and should only be used if better
|
||||
protocols aren't available.
|
||||
|
||||
When running the test master on NT, "checktime" and "timesync" are
|
||||
never needed (because there is only one client machine). Timesync
|
||||
will be ignored for NT clients, another method must be used
|
||||
(e.g. timeserv or Dimension4).
|
||||
|
||||
|
||||
Run tests:
|
||||
|
||||
Try it out. Use small process and thread counts until everything is
|
||||
working.
|
||||
|
||||
mstone pop -t 30s
|
||||
|
||||
The script will tell you how many processes and threads it is running
|
||||
on each system and where errors are logged. At the end of the test,
|
||||
it will print out a URL for the test results and an indication of the
|
||||
size of the errorlog file (stderr).
|
||||
|
||||
The results of the mstone run will display statistics for each
|
||||
protocol that was tested. The results are presented in both a HTML
|
||||
web page and a text file. The text file is simple and uniform, while
|
||||
the web page is more user readable. The web page has links to the
|
||||
test configuration files, error log, and the text version.
|
||||
|
||||
For long tests run (e.g. 8 hours), the results can be updated while
|
||||
the test is running by using the "process" utility. Don't run
|
||||
"process" near the very end of the test.
|
||||
|
||||
If a test has to be aborted, then use "process" to generate a report
|
||||
using the available data.
|
||||
|
||||
|
||||
Customize tests:
|
||||
|
||||
Copy and edit the scripts (e.g. "conf/pop.wld") to define new tests.
|
||||
The CONFIG section specifies all the attributes used in the test.
|
||||
Other sections specify the protocols to be tested and the parameters
|
||||
for them.
|
||||
|
||||
All switches can be overridden on the command line to facilitate
|
||||
easier testing. The exact configuration (include command line
|
||||
overrides) is stored with the results from each test.
|
||||
|
||||
|
||||
Maintenance:
|
||||
|
||||
You can run "mstone setup" at any time (except during a test :-) to
|
||||
update the files on the client machines.
|
||||
|
||||
Use "mstone cleanup" to remove the files created by "mstone setup".
|
||||
|
||||
After the test is finished, the directories under "tmp/" can be
|
||||
compressed or deleted to save space. All the information about a test
|
||||
run is stored in the "results/" directories.
|
||||
|
||||
|
||||
Configuring client machines:
|
||||
|
||||
Edit conf/general.wld to include CLIENT sections for each machines to
|
||||
use.
|
||||
|
||||
You can also specify the OS type for each client machine. Set the
|
||||
"Arch" parameter in each CLIENT section as appropriate (e.g. SunOS5.6,
|
||||
Linux2.2_x86, AIX4.2, HP-UXB.11.00, IRIX6.5, OSF1V4.0, WINNT4.0). The
|
||||
directories under "bin" specify the available OS types.
|
||||
|
||||
For NT4.0 clients with a UNIX test master, you will need to configure
|
||||
"command" and "tempDir" for proper operation. See the "HOSTS=winnt01"
|
||||
example in conf/sample.wld.
|
||||
|
||||
The total number of processes and threads that can be supported on a
|
||||
client is dependent on the number of commands in the test, the OS, and
|
||||
available memory. Check the stderr log for messages about not being
|
||||
able to create processes or threads. Check on the client machines
|
||||
during the test and make sure they aren't running out of CPU. The
|
||||
UNIX programs "top" and "vmstat" are good for this. If the client CPU
|
||||
is more than 75% busy, use more machines.
|
||||
|
||||
Also watch out for network saturation. You may have to use machines
|
||||
with separate networks to the server to reach full server load.
|
||||
|
||||
|
||||
Know problems:
|
||||
|
||||
There can be extraneous errors or connections after the specified end
|
||||
of the test. These are most likely do to stopping the test and should
|
||||
be ignored.
|
||||
|
||||
At the end of the test, all current connections will logout without
|
||||
any delays. This can cause very high peak loads.
|
||||
|
||||
If one process exits early (due to misconfiguration or resource
|
||||
exhaustion) and the monitoring command did not specify a count (%c),
|
||||
then the monitoring tasks will be terminated early as well.
|
||||
|
||||
Monitoring commands that specify a count (%c), may take longer than
|
||||
predicted and delay the processing of test results. This is because
|
||||
vmstat actually delays the requested time plus the time needed to
|
||||
generate the statistics summary.
|
||||
|
||||
If you are doing tests with large thread counts, you may have to run
|
||||
as root to allow mailclient to raise its resource limits.
|
||||
|
||||
The telemetry logging for SMTP, POP3, and IMAP4 is incomplete. Most
|
||||
commands are captured, but banners and message contents may be missing.
|
||||
|
||||
The MaxBlocks parameter gets divided by the total number of processes
|
||||
before starting each client. This doesn't account for clients that
|
||||
don't have commands to run.
|
||||
|
||||
The HTTP protocol used by WMAP allows connections to be dropped and
|
||||
re-connected as needed. WMAP logs this as an error and an additional
|
||||
connect. The error log must be consulted to distinguish another types
|
||||
of connection errors (timeout or connection refused) from an automatic
|
||||
re-connect.
|
||||
|
||||
The HTTP protocol test is experimental and subject to change.
|
246
mstone/Makefile
246
mstone/Makefile
|
@ -1,246 +0,0 @@
|
|||
# Makefile for mstone
|
||||
# use gmake
|
||||
# Builds each of the components and then packages everything
|
||||
|
||||
topsrcdir = .
|
||||
|
||||
CP := cp -p
|
||||
|
||||
ifndef INCLUDED_CONFIG_MK
|
||||
include $(topsrcdir)/config/config.mk
|
||||
endif
|
||||
|
||||
|
||||
# dynamically find the optional directories names
|
||||
LIBGD_DIR = $(wildcard gd?.*)
|
||||
GNUPLOT_DIR = $(wildcard gnuplot-?.*)
|
||||
PERL_DIR = $(wildcard perl5.*)
|
||||
|
||||
# file that we package
|
||||
GDFILES = gd.txt gd.html libgd.* gd.h demoin.gif gddemo giftogd webgif
|
||||
GNUPLOTFILES = gnuplot Copyright gnuplot_x11 gnuplot.1 gnuplot.gih
|
||||
|
||||
VERSION = 4.3
|
||||
TARBALL = mstone-$(VERSION)-$(NSARCH)$(OBJDIR_TAG).tar.gz
|
||||
ZIPFILE = mstone-$(VERSION)-$(NSARCH)$(OBJDIR_TAG).zip
|
||||
TARBALL_ALL = mstone-$(VERSION)-all$(OBJDIR_TAG).tar.gz
|
||||
ZIPFILE_ALL = mstone-$(VERSION)-all$(OBJDIR_TAG).zip
|
||||
|
||||
NTFILES = mstone.bat process.bat setup.bat
|
||||
|
||||
all:: usage
|
||||
|
||||
usage::
|
||||
@$(ECHO) "gmake [ release | rpackage | debug | dpackage ]"
|
||||
@$(ECHO) " [ DIST=/m/dist/mailstone/1999xxxx dist ]"
|
||||
@$(ECHO) " [ all_DBG | all_OPT ]"
|
||||
@$(ECHO) "perl is" $(PERL_DIR) ". gd is" $(LIBGD_DIR) ". gnuplot is" $(GNUPLOT_DIR) "."
|
||||
|
||||
targets:: $(OBJDIR) mailclient
|
||||
|
||||
ifneq (,$(LIBGD_DIR))
|
||||
targets:: libgd
|
||||
endif
|
||||
|
||||
ifneq (,$(GNUPLOT_DIR))
|
||||
targets:: gnuplot
|
||||
endif
|
||||
|
||||
ifneq (,$(PERL_DIR))
|
||||
targets:: perl
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
-mkdir -p $(OBJDIR)
|
||||
|
||||
mailclient::
|
||||
@$(ECHO) "\n===== [`date`] making OS_CONFIG=$(NSARCH) BUILD_VARIANT=$(BUILD_VARIANT)\n"
|
||||
cd src; $(MAKE) BUILD_VARIANT=$(BUILD_VARIANT) OBJDIR=../$(OBJDIR) PKGDIR=../$(PKGDIR) all
|
||||
|
||||
# Use our top level makefiles to drive the component builds
|
||||
libgd $(OBJDIR)/gd/libgd.a::
|
||||
$(MAKE) -f gd.mk LIBGD_DIR=$(LIBGD_DIR) libgd
|
||||
|
||||
gnuplot $(OBJDIR)/gnuplot/gnuplot::
|
||||
$(MAKE) -f gnuplot.mk LIBGD_DIR=$(LIBGD_DIR) GNUPLOT_DIR=$(GNUPLOT_DIR) gnuplot
|
||||
|
||||
perl $(OBJDIR)/perl/perl::
|
||||
$(MAKE) -f perl.mk PERL_DIR=$(PERL_DIR) perl
|
||||
|
||||
# Create packaging binary directories
|
||||
# Note: dont make gd or gnuplot here. For multi-OS, they are links
|
||||
mkpkgdirs:: $(PKGDIR)/bin $(PKGDIR)/conf $(PKGDIR)/data $(PKGDIR)/doc
|
||||
|
||||
$(PKGDIR)/bin:
|
||||
mkdir -p $(PKGDIR)/bin
|
||||
|
||||
$(PKGDIR)/conf:
|
||||
mkdir -p $(PKGDIR)/conf
|
||||
|
||||
$(PKGDIR)/data:
|
||||
mkdir -p $(PKGDIR)/data
|
||||
|
||||
$(PKGDIR)/doc:
|
||||
mkdir -p $(PKGDIR)/doc
|
||||
|
||||
$(PKGDIR)/gd:
|
||||
mkdir -p $(PKGDIR)/gd
|
||||
|
||||
$(PKGDIR)/gnuplot:
|
||||
mkdir -p $(PKGDIR)/gnuplot
|
||||
|
||||
$(PKGDIR)/perl:
|
||||
mkdir -p $(PKGDIR)/perl
|
||||
|
||||
|
||||
# operating system independent share-files (at least for Unix)
|
||||
pkg-share-files:: mkpkgdirs
|
||||
@$(ECHO) "\n===== [`date`] making package share-files...\n"
|
||||
$(CP) mstone process $(PKGDIR)
|
||||
(cd $(PKGDIR); [ ! -f setup ] || rm -f setup; ln -s mstone setup)
|
||||
(cd $(PKGDIR); [ ! -f cleanup ] || rm -f cleanup; ln -s mstone cleanup)
|
||||
(cd $(PKGDIR); [ ! -f checktime ] || rm -f checktime; ln -s mstone checktime)
|
||||
(cd $(PKGDIR); [ ! -f timesync ] || rm -f timesync; ln -s mstone timesync)
|
||||
$(CP) nsarch bin/*.pl $(PKGDIR)/bin
|
||||
$(CP) conf/*.wld conf/*.wld.in conf/*.html $(PKGDIR)/conf
|
||||
$(CP) data/*.msg $(PKGDIR)/data
|
||||
$(CP) doc/*.html doc/*.gif $(PKGDIR)/doc
|
||||
$(CP) INSTALL $(PKGDIR)
|
||||
$(CP) README $(PKGDIR)
|
||||
$(CP) ChangeLog $(PKGDIR)
|
||||
$(CP) LICENSE $(PKGDIR)
|
||||
|
||||
# split out OS specific file so that combined packaging possible (set PKGDIR)
|
||||
pkg-arch-files-gd:: $(PKGDIR)/gd $(OBJDIR)/gd/libgd.a
|
||||
$(CP) $(addprefix $(OBJDIR)/gd/, $(GDFILES)) $(PKGDIR)/gd
|
||||
-$(STRIP) $(PKGDIR)/gd/webgif $(PKGDIR)/gd/giftogd $(PKGDIR)/gd/gddemo
|
||||
|
||||
pkg-arch-files-gnuplot:: $(PKGDIR)/gnuplot $(OBJDIR)/gnuplot/gnuplot
|
||||
$(CP) $(addprefix $(OBJDIR)/gnuplot/, $(GNUPLOTFILES)) $(PKGDIR)/gnuplot
|
||||
-$(STRIP) $(PKGDIR)/gnuplot/gnuplot $(PKGDIR)/gnuplot/gnuplot_x11
|
||||
|
||||
ifneq (,$(LIBGD_DIR))
|
||||
pkg-arch-files:: pkg-arch-files-gd
|
||||
endif
|
||||
|
||||
ifneq (,$(GNUPLOT_DIR))
|
||||
pkg-arch-files:: pkg-arch-files-gnuplot
|
||||
endif
|
||||
|
||||
pkg-arch-files:: $(PKGDIR)/bin $(OBJDIR)/mailclient
|
||||
@$(ECHO) "\n===== [`date`] making package arch-files...\n"
|
||||
$(CP) $(OBJDIR)/mailclient $(PKGDIR)/bin
|
||||
-$(STRIP) $(PKGDIR)/bin/mailclient
|
||||
|
||||
pkg-perl-files:: $(PKGDIR)/bin $(OBJDIR)/perl/perl
|
||||
@$(ECHO) "\n===== [`date`] making package perl-files...\n"
|
||||
$(MAKE) -f perl.mk PERL_DIR=$(PERL_DIR) \
|
||||
BUILD_VARIANT=$(BUILD_VARIANT) \
|
||||
OBJDIR=$(OBJDIR) PKGDIR=$(PKGDIR) package-perl
|
||||
find $(PKGDIR)/perl/lib -name .packlist -exec rm {} \; -print
|
||||
-$(STRIP) $(PKGDIR)/perl/bin/perl
|
||||
-$(STRIP) $(PKGDIR)/perl/bin/a2p
|
||||
|
||||
# for combined packaging, this should not be part of pkg-arch-files
|
||||
# perl is handled seperately do to its size
|
||||
ifneq (,$(PERL_DIR))
|
||||
pkg:: pkg-perl-files
|
||||
endif
|
||||
|
||||
pkg:: targets pkg-share-files pkg-arch-files
|
||||
|
||||
tarball: build/$(TARBALL)
|
||||
|
||||
build/$(TARBALL):
|
||||
@$(ECHO) "\n===== [`date`] making os tar file...\n"
|
||||
-rm -f build/$(TARBALL)
|
||||
cd $(dir $(PKGDIR)) && tar cf - . | gzip > ../../$(TARBALL)
|
||||
|
||||
zipfile: build/$(ZIPFILE)
|
||||
|
||||
build/$(ZIPFILE):
|
||||
@$(ECHO) "\n===== [`date`] making os zip file...\n"
|
||||
-rm -f build/$(ZIPFILE)
|
||||
cd $(dir $(PKGDIR)) && zip -r -q ../../$(ZIPFILE) .
|
||||
|
||||
|
||||
########################################################################
|
||||
# Generate a combined build for every Unix OS that is already packaged
|
||||
# NT has to be done seperately because it has different file names
|
||||
# We have to nuke some old parts, because permissions wont allow overwrites
|
||||
# Finally, dont ship perl development headers and libraries
|
||||
all_DBG all_OPT::
|
||||
@$(ECHO) "===== [`date`] unified packaging for $@..."
|
||||
$(MAKE) NSARCH=$@ OBJDIR_TAG='' \
|
||||
PKGDIR=$(topsrcdir)/build/package/$@.OBJ/mstone pkg-share-files
|
||||
./ospkg.sh $@.OBJ \
|
||||
$(notdir $(shell ls -d build/package/[A-Z]*$(subst all,,$@.OBJ)))
|
||||
[ -d $(topsrcdir)/build/package/$@.OBJ/mstone/bin/WINNT4.0 ] \
|
||||
&& cp -p $(NTFILES) $(topsrcdir)/build/package/$@.OBJ/mstone; :
|
||||
-rm -f ./build/mstone-$(VERSION)-$@.tar.gz
|
||||
cd ./build/package/$@.OBJ \
|
||||
&& tar cf - . | gzip > ../../mstone-$(VERSION)-$@.tar.gz
|
||||
-rm -f ./build/mstone-$(VERSION)-$@.zip
|
||||
cd ./build/package/$@.OBJ \
|
||||
&& zip -r -q ../../mstone-$(VERSION)-$@.zip .
|
||||
|
||||
|
||||
########################################################################
|
||||
# Copy all the packaged trees to the distribution site
|
||||
# Copy in the unified tarball and zip file
|
||||
# Link mstone to mailstone for Netscape back compatibility
|
||||
# Re-map short Linux name to standard Netscape convention
|
||||
dist::
|
||||
@[ "$(DIST)" != "" ] || ($(MAKE) usage && /bin/false)
|
||||
@[ ! -d "$(DIST)" ] || ($(ECHO) "Error: $(DIST) already exists" && \
|
||||
$(MAKE) usage && /bin/false)
|
||||
mkdir -p $(DIST)
|
||||
cp -p build/mstone-$(VERSION)-all_*.*[a-z] $(DIST)/
|
||||
(cd build/package; tar cf - *.OBJ) | (cd $(DIST); tar xf - )
|
||||
for l in $(DIST)/*_???.OBJ ; do \
|
||||
(cd $$l; ln -s mstone mailstone); done
|
||||
cd $(DIST); for l in Linux*_???.OBJ ; do \
|
||||
nn=`echo $$l | sed -e 's/_OPT/_glibc_PTH_OPT/' | sed -e 's/_DBG/_glibc_PTH_DBG/'`; \
|
||||
ln -s $$l $$nn; done
|
||||
|
||||
# since the default is release mode, this can just work off a dependency
|
||||
release:: targets
|
||||
#release::
|
||||
# @$(ECHO) "\n===== [`date`] making release build..."
|
||||
# $(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT targets
|
||||
@$(ECHO) "\n===== [`date`] making release build done."
|
||||
|
||||
rpackage:: release pkg #tarball zipfile
|
||||
#rpackage:: release
|
||||
# @$(ECHO) "\n===== [`date`] making release package..."
|
||||
# $(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT pkg tarball zipfile
|
||||
@$(ECHO) "\n===== [`date`] making release package done."
|
||||
|
||||
# since the default is release mode, start a make with the right mode
|
||||
debug::
|
||||
@$(ECHO) "\n===== [`date`] making debug build..."
|
||||
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG targets
|
||||
@$(ECHO) "\n===== [`date`] making debug build done."
|
||||
|
||||
# We dont usually bother to tar up a debug build
|
||||
dpackage:: debug
|
||||
@$(ECHO) "\n===== [`date`] making debug package..."
|
||||
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG pkg
|
||||
@$(ECHO) "\n===== [`date`] making debug package done."
|
||||
|
||||
# These are old and may be broken
|
||||
cleanvariant::
|
||||
(cd src; $(MAKE) OBJDIR=../$(OBJDIR) clean)
|
||||
rm -rf $(PKGDIR)
|
||||
|
||||
clean::
|
||||
$(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT cleanvariant
|
||||
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG cleanvariant
|
||||
|
||||
distcleanvariant::
|
||||
(cd src; $(MAKE) OBJDIR=../$(OBJDIR) distclean)
|
||||
rm -rf $(OBJDIR) $(PKGDIR)
|
||||
|
||||
distclean:: clean
|
||||
$(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT distcleanvariant
|
||||
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG distcleanvariant
|
189
mstone/ToDo
189
mstone/ToDo
|
@ -1,189 +0,0 @@
|
|||
Mstone TODO List
|
||||
|
||||
Updated:
|
||||
3-20-2000 Dan Christian
|
||||
|
||||
======================================================================
|
||||
Minor improvements
|
||||
|
||||
Data reduction at each testbed client
|
||||
|
||||
Test message generator (plain and MIME styles)
|
||||
|
||||
More graphs for multiple runs
|
||||
|
||||
Option to drop a fraction of connections
|
||||
|
||||
IMAP delete without reading
|
||||
Just get the message list and delete everything. This could
|
||||
be the fastest way to drain out the store.
|
||||
|
||||
|
||||
Display MIN/MAX or standard deviation on graphs
|
||||
Gnuplot can do data points with error bars. You could either
|
||||
use MIN/MAX or the standard deviation for the error bars. There are
|
||||
issues with calculating the standard deviation numbers throughout the
|
||||
graph that need to be addressed.
|
||||
|
||||
|
||||
Statistics reset
|
||||
At least the MIN and MAX statistics could be easily reset
|
||||
during the test (after ramp up). This keeps the transients during
|
||||
startup and shutdown from dominating these numbers. The standard
|
||||
deviation statistics are much trickier to reset during the run. It
|
||||
may be better to isolate sections in post processing.
|
||||
|
||||
|
||||
Perl web server
|
||||
Sometimes it would be nice to include our own web server to
|
||||
provide the results (instead of using file: URLs). This would also be
|
||||
a gateway to form based test configuration editing and allow results
|
||||
to be interactively updated during tests. Perl with a socket library
|
||||
could handle this without too much trouble.
|
||||
|
||||
|
||||
Dynamic test loading
|
||||
Finalize an API for dynamically loading tests. This would
|
||||
allow tests to be added or updated separately from the core
|
||||
functionality. This may be needed for some types of security testing.
|
||||
|
||||
|
||||
Link graphs to the results tables
|
||||
There are already tags by each graph. You should be able to
|
||||
link the appropriate results table entry to each graph. This sort of
|
||||
tricky since graphs often combine multiple entries.
|
||||
|
||||
|
||||
Show statistics for every block
|
||||
Statistics are actually kept for every block in every thread.
|
||||
There should be a way to view information at this detail.
|
||||
|
||||
|
||||
Man pages
|
||||
The online docs are nice, but good 'ol man pages would be
|
||||
great in a different way.
|
||||
|
||||
|
||||
Reduce namespace polution
|
||||
Scripts names like setup and cleanup are too general. They
|
||||
|
||||
should be part of the main 'mstone' script (e.g. mstone setup).
|
||||
|
||||
Examples of script series
|
||||
Include example scripts to run entire series of tests in a
|
||||
sane way.
|
||||
|
||||
|
||||
Fix FORMAT clash
|
||||
At the start of a test, each client process outputs the
|
||||
information needed to report all its protocols. When there are
|
||||
multiple processes on one client, these FORMAT lines can intermix and
|
||||
cause parsing errors.
|
||||
|
||||
|
||||
Set connection drop rate
|
||||
Drop some percentage of the connections without a proper
|
||||
shutdown. This tests how well a server can detect and recover from
|
||||
hard disconnects.
|
||||
|
||||
|
||||
Improve randomness
|
||||
The way that we generate random numbers in a range may be not
|
||||
generate the proper randomness. We are using lrand48()%range we
|
||||
should use (lrand48/RAND_RANGE)*range. There are some end conditions
|
||||
that need to be thought about. All of this is in the sequence code;
|
||||
one change should fix (or break :) everything.
|
||||
|
||||
Also, we may be generating numbers that are never used. This
|
||||
may be costly, and can create holes in the proper sequence.
|
||||
|
||||
|
||||
Improve printing
|
||||
The color graphs are great on screen, but tend to print
|
||||
poorly. Either we need a better way to generate a printable version
|
||||
(maybe through a CGI button), or the seperate protocols need to be
|
||||
printed individually. Also, Communicator does a lousy job of keeping
|
||||
title with tables or graphs. Hopefully, Mozilla will do better.
|
||||
|
||||
|
||||
======================================================================
|
||||
Whole new protocol tests:
|
||||
|
||||
ICQ
|
||||
Test high volume instant messaging. Very useful for the
|
||||
bridges and gateways that people are considering using.
|
||||
|
||||
|
||||
WAP
|
||||
WAP is the emerging standard for mobile phones.
|
||||
|
||||
|
||||
WCAP
|
||||
Web based calendar services
|
||||
|
||||
|
||||
LDAP
|
||||
Use the LDAP SDK to do basic LDAP testing. The SDK probably
|
||||
isn't fast enough to call this a real performance test, but you can at
|
||||
least test performance degredation due to load from a real application
|
||||
(like a mail server).
|
||||
|
||||
|
||||
DNS
|
||||
Mail servers use DNS a lot. You should at least be able to
|
||||
see if performance is degrading due to load.
|
||||
|
||||
|
||||
Disk/filesystem
|
||||
Test read, write, sync, link, un-link, and append performance under
|
||||
multiple threads.
|
||||
|
||||
|
||||
Cert servers
|
||||
Test certificate authenticity checking performance
|
||||
|
||||
|
||||
======================================================================
|
||||
Possible dummy servers:
|
||||
|
||||
SMTP
|
||||
Receive mail via SMTP and ignore it. Usefull for SMTP relay
|
||||
testing.
|
||||
|
||||
|
||||
DNS
|
||||
Simulate slow DNS server lookups. Usefull for SMTP relay testing.
|
||||
|
||||
|
||||
======================================================================
|
||||
Major changes
|
||||
|
||||
Throttling
|
||||
Monitor and control transaction rates so that specific load
|
||||
levels can be easily specified. The rates should be able to vary to
|
||||
simulate peek hour usage and disconnect-restore.
|
||||
|
||||
|
||||
NSPR threading
|
||||
Use NSPR for threading and sockets. This may allow other OSes
|
||||
to be used as clients. This might be easy, since mstone does not need
|
||||
any locking, just simple thread creation and harvesting. NSPR
|
||||
argument parsing and hashes may also be useful.
|
||||
|
||||
|
||||
SSL
|
||||
Support SSL on the protocols that allow it. May require NSPR.
|
||||
|
||||
|
||||
Line speed emulation
|
||||
Simulate the variable delays and limited throughput of dial up
|
||||
connections.
|
||||
|
||||
|
||||
Scripting
|
||||
Allow more detailed control of protocol tests. It looks
|
||||
difficult to make this scalable and fast.
|
||||
|
||||
|
||||
Combined tests
|
||||
Deliver mail over SMTP and then see when it arrives using IMAP.
|
462
mstone/allbuild
462
mstone/allbuild
|
@ -1,462 +0,0 @@
|
|||
#!/bin/ksh
|
||||
########################################################################
|
||||
# buildall - automated multi-platform build tool
|
||||
#
|
||||
# 10/09/97 - marcel - created
|
||||
# 10/13/97 - marcel - support shared build tree
|
||||
# 2/11/98 - marcel - updated for 4.0 Beta builds (need -update)
|
||||
# 2/26/98 - marcel - added -r, -t and host specifiers
|
||||
# 7/01/99 - robodan - added VAR=value ability
|
||||
# 8/01/99 - robodan - explicitly know about building on localhost
|
||||
# 10/15/99 - robodan - remove older OSes from build list
|
||||
# 2000/4/7 - robodan - Created mstone version
|
||||
########################################################################
|
||||
#
|
||||
# This script is intended to do a set of UNIX builds for a
|
||||
# given CVS module. It is designed to use 'rsh' between a
|
||||
# set of trusting hosts and use shared NFS storage with common
|
||||
# mount points (e.g. /u/username/...)
|
||||
#
|
||||
# To check if you have rights to rsh to a particular host, try:
|
||||
# rsh hostname "echo $PATH"
|
||||
# You may have to edit your .rhosts or /etc/hosts.equiv
|
||||
#
|
||||
# A target directory will be created based on the current date.
|
||||
#
|
||||
# A set of global build logs plus a log per platform are kept
|
||||
# in a log directory under the target
|
||||
#
|
||||
# It will checkout a copy of the source, duplicate it for
|
||||
# each platform and perform a set of remote builds in parallel.
|
||||
# The script will exit when all the work has been completed.
|
||||
#
|
||||
# Example usage:
|
||||
# cd ~/src; buildall msg
|
||||
# Result:
|
||||
# ~/src/19980210_40.1/
|
||||
# ~/src/19980210_40.1/logs/...
|
||||
# ~/src/19980210_40.1/src/...
|
||||
# ...
|
||||
#
|
||||
|
||||
# Buildhosts
|
||||
DEFAULT_BUILDHOSTS="kimo nugget vsync shave purgatory trex0"
|
||||
|
||||
usage() {
|
||||
echo ""
|
||||
echo "usage: buildall [ make assigns... ] < -t | target > [ -r ] [ buildhosts... ]"
|
||||
echo " [ -t | --test]: just test rsh and report OS versions."
|
||||
echo " [-r | --respin]: rebuild in place using existing source."
|
||||
echo " [-p | --postbuild]: Execute post build command too."
|
||||
echo " [make assigns]: e.g. VARIANT=release"
|
||||
echo " <target>: one of: mstone42"
|
||||
echo " [buildhosts...]: default [$DEFAULT_BUILDHOSTS]"
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Set these defaults and options for your desired build
|
||||
########################################################################
|
||||
|
||||
# Target base destination directory
|
||||
DESTBASE=`pwd`
|
||||
|
||||
# Can we do multiple ARCH builds in same source tree
|
||||
SHARESRC=yes
|
||||
|
||||
DESCRIPTION=""
|
||||
BUILDHOSTS=""
|
||||
RESPIN="no"
|
||||
POSTBUILD="no"
|
||||
JUST_TEST="no"
|
||||
DESTTYPE=""
|
||||
CO_CMD="cvs -d $CVSROOT -q checkout"
|
||||
CHECKOUT=""
|
||||
CHECKOUT2=""
|
||||
#MOZCVSROOT=':pserver:anonymous@cvs.mozilla.org:/cvsroot'
|
||||
MOZCVSROOT=':pserver:robodan%netscape.com@cvs.mozilla.org:/cvsroot'
|
||||
|
||||
MAKE="gmake"
|
||||
MK_ARG=""
|
||||
|
||||
ARGS="$@"
|
||||
|
||||
for ARG in "$@"; do
|
||||
|
||||
# If this is a make assignment (FOO=whatever), add it to make command
|
||||
# Arguments with quotes in them dont go all the way through.
|
||||
# Make args trick: 'FOO=nop -j 2'
|
||||
# The pre-post arg stuff uses hostnames as a switch, ugly calling syntax.
|
||||
if [[ -n "`echo z$ARG | egrep '^z[A-Z0-9_]+=[^ ]'`" ]] ; then
|
||||
if [[ -n "$DESCRIPTION" ]] ; then
|
||||
echo "Arg after target is ignored! ($ARG)"
|
||||
continue
|
||||
fi
|
||||
if [[ -z "$BUILDHOSTS" ]] ; then # pre args
|
||||
MAKE="$MAKE $ARG"
|
||||
else # post args
|
||||
MK_ARG="$MK_ARG $ARG"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
# should we just rebuild todays latest source...
|
||||
if [[ "$ARG" = "-r" || "$ARG" = "--respin" || "$ARG" = "respin" ]]; then
|
||||
RESPIN="yes"
|
||||
continue
|
||||
fi
|
||||
|
||||
# should we just run post build command...
|
||||
if [[ "$ARG" = "-p" || "$ARG" = "--postbuild" || "$ARG" = "postbuild" ]]; then
|
||||
POSTBUILD="yes"
|
||||
continue
|
||||
fi
|
||||
|
||||
# should we just test remote connectivity and execute permissions...
|
||||
if [[ "$ARG" = "-t" || "$ARG" = "--test" ]]; then
|
||||
JUST_TEST="yes"
|
||||
RESPIN="yes"
|
||||
continue
|
||||
fi
|
||||
|
||||
# We will pull source using: "$CHECKOUT"
|
||||
# And build on each machine: "cd $BUILDDIR && $BUILDCMD"
|
||||
|
||||
|
||||
# expand targets (but dont confuse hosts for targets (msg7))
|
||||
|
||||
# These will build just mstone
|
||||
# expand targets (but dont confuse hosts for targets (msg7))
|
||||
if [[ "$BUILDCMD" = "" && "$ARG" = mailstone* ]]; then
|
||||
case ${ARG#mstone} in
|
||||
"")
|
||||
"42")
|
||||
DESTTYPE=_MSTONE42
|
||||
MS_BRANCH=""
|
||||
#BUILDCMD="$MAKE $MK_ARG debug release"
|
||||
#POSTCMD="$MAKE $MK_ARG all_DBG.OBJ all_OPT.OBJ"
|
||||
BUILDCMD="$MAKE $MK_ARG rpackage"
|
||||
POSTCMD="$MAKE $MK_ARG all_OPT"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown mstone version in $ARG"
|
||||
echo "Try mstone42"
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
DESCRIPTION="Mstone $MS_BRANCH"
|
||||
BUILDDIR=./mozilla/mstone
|
||||
CVSROOT=$MOZCVSROOT
|
||||
CHECKOUT="$CO_CMD $MS_BRANCH mozilla/mstone"
|
||||
# BUG No way to unpack perl, gd, and gnuplot before building
|
||||
continue
|
||||
fi
|
||||
|
||||
#########################
|
||||
# Other...
|
||||
#########################
|
||||
|
||||
# These will print some tools info
|
||||
if [[ "$ARG" = "tools" ]]; then
|
||||
CHECKOUT="$CO_CMD modules"
|
||||
BUILDDIR=.
|
||||
BUILDCMD="which gcc && ls -l /tools/ns/bin/gcc && which gcc-2.7.2.1 && ls -l /tools/ns/bin/gcc-2.7.2.1"
|
||||
continue
|
||||
fi
|
||||
|
||||
#########################
|
||||
# Everything else is assumed to be a hostname
|
||||
#########################
|
||||
|
||||
BUILDHOSTS="$ARG $BUILDHOSTS"
|
||||
|
||||
done # for ARG in $*; do
|
||||
|
||||
if [[ "$BUILDHOSTS" = "" ]]; then
|
||||
BUILDHOSTS=$DEFAULT_BUILDHOSTS
|
||||
fi
|
||||
|
||||
if [[ "$BUILDCMD" = "" && "$JUST_TEST" = "no" ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# You shouldn't have to modify stuff below here too much
|
||||
########################################################################
|
||||
|
||||
# Who and Where are we
|
||||
PROG=buildall
|
||||
RSH=rsh
|
||||
SYS=`uname -s`
|
||||
echo SYS=$SYS
|
||||
if [[ "$SYS" = "HP-UX" ]]; then
|
||||
RSH=remsh
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# Simple log output function
|
||||
########################################################################
|
||||
|
||||
log() {
|
||||
# echo "[`date +\"%Y/%m/%d %H:%M:%S\"`] $PROG: $*"
|
||||
echo "`date +\"%H:%M:%S\"` $PROG: $*"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Error
|
||||
########################################################################
|
||||
|
||||
quit() {
|
||||
log "$* (exiting)..."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Where should the work be done
|
||||
REV=1
|
||||
WORKDIR=$DESTBASE/`date +"%Y%m%d"`$DESTTYPE.$REV
|
||||
LASTWORKDIR=$WORKDIR
|
||||
LASTREV=$REV
|
||||
|
||||
while [[ -d $WORKDIR ]]; do
|
||||
LASTREV=$REV
|
||||
let "REV= REV + 1"
|
||||
LASTWORKDIR=$WORKDIR
|
||||
WORKDIR=$DESTBASE/`date +"%Y%m%d"`$DESTTYPE.$REV
|
||||
done
|
||||
|
||||
if [[ "$RESPIN" = "yes" ]]; then
|
||||
WORKDIR=$LASTWORKDIR
|
||||
REV=$LASTREV
|
||||
fi
|
||||
BUILDREV=$REV
|
||||
|
||||
if [[ ! -d $WORKDIR && "$RESPIN" = "yes" ]]; then
|
||||
quit "missing expected respin workdir ($WORKDIR)"
|
||||
fi
|
||||
|
||||
mkdir -p $WORKDIR
|
||||
|
||||
# Where to send logs
|
||||
LOGDIR=$WORKDIR/logs
|
||||
[[ -d $LOGDIR ]] || mkdir $LOGDIR
|
||||
|
||||
# What tool to use for compressed tar
|
||||
if [[ -x /tools/ns/bin/tar ]] ; then # ROBDAN 9-15-98 for Linux
|
||||
TAR=/tools/ns/bin/tar
|
||||
else
|
||||
TAR=tar
|
||||
fi
|
||||
|
||||
SRCDIR=$WORKDIR/src
|
||||
SRCTAR=$WORKDIR/src.tar.gz
|
||||
|
||||
########################################################################
|
||||
# The function which extracts the source and prepares for copies
|
||||
########################################################################
|
||||
|
||||
prepare_source() {
|
||||
log "Preparing source code..."
|
||||
mkdir $SRCDIR
|
||||
(cd $SRCDIR;
|
||||
log "Extracting source in $SRCDIR...";
|
||||
log "$CHECKOUT > $LOGDIR/cvs-co.txt";
|
||||
$CHECKOUT > $LOGDIR/cvs-co.txt;
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $CHECKOUT"; fi
|
||||
if [[ "$CHECKOUT2" != "" ]]; then
|
||||
log "$CHECKOUT2 >> $LOGDIR/cvs-co.txt";
|
||||
$CHECKOUT2 >> $LOGDIR/cvs-co.txt;
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $CHECKOUT2"; fi
|
||||
fi
|
||||
log "Listing source...";
|
||||
ls -Rl > $LOGDIR/src-ls-Rl.txt
|
||||
log "Archiving source..."
|
||||
$TAR czf $SRCTAR .
|
||||
)
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then
|
||||
quit "### Failed($RET): cannot prepare source";
|
||||
else
|
||||
log "Source extraction complete";
|
||||
fi
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# The function which does a build
|
||||
########################################################################
|
||||
|
||||
do_rbuild() {
|
||||
OSDEST=$1
|
||||
|
||||
if [ "$SHARESRC" = "yes" ]; then
|
||||
RSRCDIR=$SRCDIR
|
||||
else
|
||||
RSRCDIR=$WORKDIR/$OSDEST
|
||||
fi
|
||||
|
||||
[[ -d $RSRCDIR ]] || mkdir -p $RSRCDIR
|
||||
|
||||
cd $RSRCDIR;
|
||||
|
||||
# do any late variable expansions
|
||||
RAWCMD=$BUILDCMD
|
||||
BUILDCMD=$(eval echo $RAWCMD)
|
||||
|
||||
if [[ $RHOST = localhost ]] ; then
|
||||
log "Build locally for $OSDEST ($BUILDCMD)...";
|
||||
cd $BUILDDIR && pwd && $BUILDCMD && echo $PROG: Success
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $OSDEST build"; fi
|
||||
|
||||
log "Completed local build..."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$SHARESRC" != "yes" ]]; then
|
||||
log "Extracting source for $OSDEST...";
|
||||
$RSH $RHOST -n "cd $RSRCDIR && pwd && $TAR xzf $SRCTAR";
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $OSDEST source extraction"; fi
|
||||
else
|
||||
log "Using common source in $RSRCDIR";
|
||||
fi
|
||||
|
||||
log "Building for $OSDEST ($BUILDCMD)...";
|
||||
$RSH $RHOST -n "cd $RSRCDIR/$BUILDDIR && pwd && $BUILDCMD && echo $PROG: Success"
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $OSDEST build"; fi
|
||||
|
||||
log "Completed $OSDEST...";
|
||||
}
|
||||
|
||||
buildhost() {
|
||||
RHOST=$1
|
||||
|
||||
log "Query $RHOST configuration...";
|
||||
|
||||
if [[ $RHOST = localhost ]] ; then
|
||||
uname -s > /tmp/$$.$RHOST 2>&1
|
||||
else
|
||||
$RSH $RHOST -n "uname -s" > /tmp/$$.$RHOST 2>&1
|
||||
RET=$?
|
||||
if [[ $RET -ne 0 ]]; then
|
||||
quit "..[$RHOST] ### Failed($RET): $RSH $RHOST -n \"uname -s\"";
|
||||
fi
|
||||
fi
|
||||
ROSTYPE=`tail -1 /tmp/$$.$RHOST`
|
||||
|
||||
if [[ "$ROSTYPE" = "AIX" ]]; then
|
||||
$RSH $RHOST -n "uname -v" > /tmp/$$.$RHOST 2>&1
|
||||
ROSTYPE=${ROSTYPE}`tail -1 /tmp/$$.$RHOST`
|
||||
fi
|
||||
|
||||
if [[ $RHOST = localhost ]] ; then
|
||||
uname -r > /tmp/$$.$RHOST 2>&1
|
||||
else
|
||||
$RSH $RHOST -n "uname -r" > /tmp/$$.$RHOST 2>&1
|
||||
fi
|
||||
ROSREV=`tail -1 /tmp/$$.$RHOST`
|
||||
rm /tmp/$$.$RHOST
|
||||
|
||||
if [[ $RHOST = localhost ]] ; then
|
||||
OSDEST=`hostname | cut -f1 -d.`-${ROSTYPE}${ROSREV}
|
||||
else
|
||||
OSDEST=${RHOST}-${ROSTYPE}${ROSREV}
|
||||
fi
|
||||
log "..Building on [$OSDEST]..."
|
||||
|
||||
REV=1 # find unique logfile name
|
||||
OSLOG=$LOGDIR/$OSDEST.$REV
|
||||
while [[ -f $OSLOG ]]; do
|
||||
let "REV = REV + 1"
|
||||
OSLOG=$LOGDIR/$OSDEST.$REV
|
||||
done
|
||||
|
||||
if [[ "$JUST_TEST" = "yes" ]]; then
|
||||
echo "$PROG: Success" > $OSLOG
|
||||
else
|
||||
( do_rbuild $OSDEST ) > $OSLOG 2>&1
|
||||
fi
|
||||
|
||||
grep "$PROG: Success" $OSLOG > /dev/null
|
||||
RET=$?
|
||||
if [[ $RET -eq 0 ]]; then
|
||||
RESULT="SUCCESS";
|
||||
else
|
||||
RESULT="FAILURE($RET)";
|
||||
fi
|
||||
log "..Completed [$OSDEST] <$RESULT>.";
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# The function which initiates all the builds
|
||||
########################################################################
|
||||
|
||||
do_builds() {
|
||||
log "Launching builds..."
|
||||
|
||||
for HOST in $BUILDHOSTS; do
|
||||
buildhost $HOST &
|
||||
done
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# main
|
||||
########################################################################
|
||||
|
||||
main() {
|
||||
if [[ "$JUST_TEST" = "yes" ]]; then
|
||||
log "Automated test starting..."
|
||||
else
|
||||
log "Automated build of [$DESCRIPTION] starting..."
|
||||
fi
|
||||
log ""
|
||||
log " ARGS = $ARGS"
|
||||
log " BUILDHOSTS = $BUILDHOSTS"
|
||||
log " WORKDIR = $WORKDIR"
|
||||
log " SRCDIR = $SRCDIR"
|
||||
log " LOGDIR = $LOGDIR"
|
||||
log " CHECKOUT = $CHECKOUT"
|
||||
log " BUILDDIR = $BUILDDIR"
|
||||
log " BUILDCMD = $BUILDCMD"
|
||||
log " RESPIN = $RESPIN"
|
||||
log ""
|
||||
|
||||
[[ "$RESPIN" = "no" ]] && prepare_source
|
||||
do_builds
|
||||
log "Waiting for all builds to complete..."
|
||||
wait
|
||||
log "All builds completed."
|
||||
|
||||
if [[ -n "$POSTCMD" && "$POSTBUILD" = "yes" ]] ; then
|
||||
log "Running post build command."
|
||||
|
||||
REV=1 # find unique logfile name
|
||||
POSTLOG=$LOGDIR/postbuild.$REV
|
||||
while [[ -f $POSTLOG ]]; do
|
||||
let "REV = REV + 1"
|
||||
POSTLOG=$LOGDIR/postbuild.$REV
|
||||
done
|
||||
|
||||
echo "Dir $SRCDIR/$BUILDDIR" > $POSTLOG
|
||||
echo "Cmd $POSTCMD" >> $POSTLOG
|
||||
(cd $SRCDIR/$BUILDDIR && $POSTCMD && echo $PROG: Success) >> $POSTLOG 2>&1
|
||||
|
||||
log "Post build command completed."
|
||||
elif [[ -n "$POSTCMD" ]] ; then
|
||||
echo "Skipping post build command: $POSTCMD"
|
||||
fi
|
||||
}
|
||||
|
||||
REV=1
|
||||
PROGLOG=$LOGDIR/$PROG.$REV
|
||||
|
||||
while [[ -f $PROGLOG ]]; do
|
||||
REV=`expr $REV + 1`
|
||||
PROGLOG=$LOGDIR/$PROG.$REV
|
||||
done
|
||||
|
||||
main | tee $PROGLOG 2>&1
|
||||
exit 0
|
|
@ -296,7 +296,7 @@ sub kformat {
|
|||
|
||||
# simple function to formatted a time into Ns, Nms, or Nus
|
||||
# the goal is to make a table of timss uncluttered and easy to read
|
||||
# I dont convert to minutes or hours because the non-1000x multipliers
|
||||
# I don't convert to minutes or hours because the non-1000x multipliers
|
||||
# are hard to back solve in your head for comparisons
|
||||
sub tformat {
|
||||
my $n = shift;
|
||||
|
|
|
@ -1,576 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Mailstone utility,
|
||||
# released March 17, 2000.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
# Marcel DePaolis <marcel@netcape.com>
|
||||
# Mike Blakely
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
#####################################################
|
||||
|
||||
# see setup.pl for full usage
|
||||
# mailmaster [-d] [-c <config file>] ...
|
||||
|
||||
# This script reads in the client configuration files and will
|
||||
# fork children to rsh the mailclient process on network clients,
|
||||
# each child will write test results to /mailstone directory before
|
||||
# dying. The parent will the read and combine the results.
|
||||
#
|
||||
# Make sure the user running this script has rsh privilege across
|
||||
# all client machines
|
||||
|
||||
print "Netscape Mailstone version 4.2\n";
|
||||
print "Copyright (c) Netscape Communications Corp. 1997-2000\n";
|
||||
|
||||
# this parses the command line and config file
|
||||
do 'args.pl'|| die "$@\n";
|
||||
parseArgs(); # parse command line
|
||||
|
||||
{ # get unique date string
|
||||
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
|
||||
my $tstamp = sprintf ("%04d%02d%02d.%02d%02d",
|
||||
1900+$year, 1+$mon, $mday, $hour, $min);
|
||||
|
||||
if ( -d "$resultbase/$tstamp") { # check for runs within a minute
|
||||
my $tail = 'a';
|
||||
while ( -d "$resultbase/$tstamp$tail" ) { $tail++; }
|
||||
$tstamp .= $tail;
|
||||
}
|
||||
$params{TSTAMP} = $tstamp;
|
||||
}
|
||||
|
||||
$resultdir = "$resultbase/$params{TSTAMP}";
|
||||
$tmpdir = "$tmpbase/$params{TSTAMP}";
|
||||
$resultstxt = "$resultdir/results.txt";
|
||||
$resultshtml = "$resultdir/results.html";
|
||||
mkdir ("$resultbase", 0775);
|
||||
mkdir ("$tmpbase", 0775);
|
||||
mkdir ("$resultdir", 0775);
|
||||
mkdir ("$tmpdir", 0775);
|
||||
|
||||
# Make sure we have everything
|
||||
die "Must specify the test time" unless $params{TIME};
|
||||
die "Must specify a workload file" unless $params{WORKLOAD};
|
||||
|
||||
if ($params{TESTBED}) { # BACK COMPATIBILITY
|
||||
readTestbedFile ($params{TESTBED}) || die "Error reading testbed: $@\n";
|
||||
}
|
||||
|
||||
$testsecs = figureTimeSeconds ($params{TIME}, "seconds");
|
||||
|
||||
# figure out the processes and thread, given the desired number
|
||||
# takes into account all the constraints. todo can be a float.
|
||||
sub figurePT {
|
||||
my $sec = shift;
|
||||
my $todo = shift;
|
||||
my $p = 1; # first guess
|
||||
my $t = 1;
|
||||
my $start = 1; # initial process guess
|
||||
my $end = 250; # highest process guess
|
||||
|
||||
if ($todo < 1) { # mark this client as inactive
|
||||
$sec->{PROCESSES} = 0;
|
||||
$sec->{THREADS} = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (($section->{MAXCLIENTS}) && ($todo > $section->{MAXCLIENTS})) {
|
||||
$todo = $section->{MAXCLIENTS}; # trim to max client per host
|
||||
}
|
||||
if ($section->{PROCESSES}) { # they set this part already
|
||||
$start = int ($section->{PROCESSES});
|
||||
$end = $start;
|
||||
$p = $start;
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
print "Using specified $p processes for clients $slist\n";
|
||||
}
|
||||
|
||||
$end = int ($section->{MAXPROCESSES})
|
||||
if ($section->{MAXPROCESSES}); # they set a max
|
||||
|
||||
if (($params{NT}) || ($section->{ARCH} eq "NT4.0")) {
|
||||
$end = 1; # # NT is currently limited to 1 process
|
||||
$start = 1;
|
||||
$p = 1;
|
||||
}
|
||||
|
||||
# step through some process counts
|
||||
# it should first reduce errors due to MAXTHREADS,
|
||||
# the it will reduce errors due to integer math.
|
||||
# not optimal, just good enough
|
||||
my $misses = 0;
|
||||
for (my $n = $start; $n <= $end; $n++) { # try some process counts
|
||||
my $tryt = int ($todo / $n);
|
||||
if (($sec->{MAXTHREADS}) && ($tryt > $sec->{MAXTHREADS})) {
|
||||
$tryt = $sec->{MAXTHREADS};
|
||||
}
|
||||
# see if this is a better match than the last one
|
||||
if (abs ($todo - ($n * $tryt)) < abs ($todo - ($p * $t))) {
|
||||
$p = $n;
|
||||
$t = $tryt;
|
||||
$misses = 0;
|
||||
} else {
|
||||
$misses++;
|
||||
last if ($misses > 1); # getting worse
|
||||
}
|
||||
}
|
||||
$sec->{PROCESSES} = $p;
|
||||
$sec->{THREADS} = $t;
|
||||
return $p * $t;
|
||||
}
|
||||
|
||||
# Allocate CLIENTCOUNT to the client machines
|
||||
# try NOT to turn this into a massive linear programming project
|
||||
# works best to put bigger machines last
|
||||
if ($params{CLIENTCOUNT}) {
|
||||
my $todo = $params{CLIENTCOUNT};
|
||||
my $softcli = 0; # how many can we play with
|
||||
|
||||
foreach $section (@workload) { # see which are already fixed
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
unless (($section->{PROCESSES}) && ($section->{THREADS})) {
|
||||
$softcli++;
|
||||
next;
|
||||
}
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my @hlist = split /[\s,]/, $slist;
|
||||
my $hcnt = (1 + $#hlist);
|
||||
|
||||
# subtract fixed entries
|
||||
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 1;
|
||||
$todo -= $tcount * $section->{PROCESSES} * $hcnt;
|
||||
$clientProcCount += $section->{PROCESSES} * $hcnt; # total processes
|
||||
$params{DEBUG} &&
|
||||
print "Fixed load group with $hcnt hosts: $section->{PROCESSES} x $tcount\n";
|
||||
}
|
||||
|
||||
$params{DEBUG} &&
|
||||
print "Allocating $todo clients over $softcli groups\n";
|
||||
if ($softcli) {
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
next if (($section->{PROCESSES}) && ($section->{THREADS}));
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my @hlist = split /[\s,]/, $slist;
|
||||
my $hcnt = (1 + $#hlist);
|
||||
|
||||
#print "todo=$todo softcli=$softcli hcnt=$hcnt\n";
|
||||
$todo -= $hcnt * figurePT ($section, $todo / ($softcli * $hcnt));
|
||||
$clientProcCount += $hcnt * $section->{PROCESSES}; # total procs
|
||||
|
||||
$softcli--;
|
||||
last if ($softcli <= 0); # should not happen
|
||||
}
|
||||
}
|
||||
if ($todo) {
|
||||
print "Warning: Could not allocate $todo of $params{CLIENTCOUNT} clients.\n";
|
||||
$params{CLIENTCOUNT} -= $todo;
|
||||
}
|
||||
|
||||
|
||||
} else { # figure out the client count
|
||||
my $cnt = 0;
|
||||
foreach $section (@workload) { # see which are already fixed
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
next unless ($section->{PROCESSES});
|
||||
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my @hlist = split /[\s,]/, $slist;
|
||||
my $hcnt = (1 + $#hlist);
|
||||
|
||||
# subtract fixed entries
|
||||
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 1;
|
||||
$cnt += $tcount * $section->{PROCESSES} * $hcnt;
|
||||
$clientProcCount += $section->{PROCESSES} * $hcnt; # total processes
|
||||
}
|
||||
$params{CLIENTCOUNT} = $cnt;
|
||||
die "No clients configured!\n" unless ($cnt > 0);
|
||||
}
|
||||
|
||||
# This has to be written into save workload file for later processing
|
||||
unless ($params{FREQUENCY}) { # unless frequency set on command line
|
||||
my $chartp = ($params{CHARTPOINTS}) ? $params{CHARTPOINTS} : 464;
|
||||
|
||||
# approximate data points for good graphs (up to 2 times this)
|
||||
$params{FREQUENCY} = int ($testsecs / $chartp);
|
||||
if ($params{FREQUENCY} < 2) { # fastest is every 2 seconds
|
||||
$params{FREQUENCY} = 2;
|
||||
} elsif ($params{FREQUENCY} > 60) { # slowest is every minute
|
||||
$params{FREQUENCY} = 60;
|
||||
}
|
||||
}
|
||||
|
||||
{ # set a unique block id on every section
|
||||
my $id = 0;
|
||||
my $configSeen = 0;
|
||||
my $defaultSeen = 0;
|
||||
foreach $section (@workload) {
|
||||
if ($section->{"sectionTitle"} =~ /^CONFIG$/) {
|
||||
next if $configSeen;
|
||||
$configSeen++;
|
||||
}
|
||||
if ($section->{"sectionTitle"} =~ /^DEFAULT$/) {
|
||||
next if $defaultSeen;
|
||||
$defaultSeen++;
|
||||
}
|
||||
$id++; # number 1, 2, ...
|
||||
if ($section->{"sectionTitle"} =~ /^(CONFIG|CLIENT)$/) {
|
||||
$section->{BLOCKID} = $id;
|
||||
} else {
|
||||
push @{$section->{"lineList"}}, "blockID\t$id\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Write the version we pass to mailclient
|
||||
writeWorkloadFile ("$resultdir/work.wld", \@workload,
|
||||
\@scriptWorkloadSections);
|
||||
|
||||
# Write the complete inclusive version
|
||||
writeWorkloadFile ("$resultdir/all.wld", \@workload);
|
||||
|
||||
setConfigDefaults(); # pick up any missing defaults
|
||||
|
||||
unless ($#protocolsAll > 0) {
|
||||
die "No protocols found. Test Failed!\n";
|
||||
}
|
||||
|
||||
print "Starting: ", scalar(localtime), "\n";
|
||||
|
||||
# redirect STDERR
|
||||
open SAVEERR, ">&STDERR";
|
||||
open(STDERR, ">$resultdir/stderr") || warn "Can't redirect STDERR:$!\n";
|
||||
|
||||
$totalProcs = 0; # number of clients started
|
||||
|
||||
# iterate over every client in the testbed, complete the cmd and rsh
|
||||
if ($params{NT}) { # single client on local host
|
||||
pathprint ("Starting clients (errors logged to $resultdir/stderr)\n");
|
||||
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 1;
|
||||
|
||||
|
||||
# Build the initial Mailclient command line
|
||||
my $preCmd = ($section->{COMMAND})
|
||||
? $section->{COMMAND} : $params{CLIENTCOMMAND};
|
||||
$preCmd .= " -s -t $params{TIME} -f $params{FREQUENCY}";
|
||||
$preCmd .= " -d" if ($params{DEBUG});
|
||||
$preCmd .= " -r" if ($params{TELEMETRY});
|
||||
$preCmd .= " -R $params{RAMPTIME}" if ($params{RAMPTIME});
|
||||
$preCmd .= " -m $params{MAXERRORS}" if ($params{MAXERRORS});
|
||||
$preCmd .= " -M $params{MAXBLOCKS}" if ($params{MAXBLOCKS});
|
||||
$preCmd .= " -n 1 -N $tcount";
|
||||
$preCmd .= ($params{USEGROUPS} && $section->{GROUP})
|
||||
? " -H $section->{GROUP}" : " -H $cli";
|
||||
|
||||
my $stdout = "$tmpdir/localhost.out";
|
||||
|
||||
$totalProcs += $tcount;
|
||||
do 'makeindex.pl' || warn "$@\n"; # html index
|
||||
|
||||
printf "\nTest duration: %d %s. Rampup time: %d %s. Number of clients: %d\n",
|
||||
figureTimeNumber ($params{TIME}),
|
||||
figureTimeUnits ($params{TIME}, "seconds"),
|
||||
figureTimeNumber ($params{RAMPTIME}),
|
||||
figureTimeUnits ($params{RAMPTIME}, "seconds"),
|
||||
$totalProcs;
|
||||
|
||||
print STDERR "localhost: cd $params{TEMPDIR}; $preCmd\n";
|
||||
|
||||
# Redirect STDIN, and STDOUT
|
||||
#open SAVEIN, "<STDIN";
|
||||
open STDIN, "<$resultdir/work.wld"
|
||||
|| die "Coundn't open $resultdir/work.wld for input\n";
|
||||
open SAVEOUT, ">&STDOUT";
|
||||
open STDOUT, ">$stdout"
|
||||
|| die "Couldnt open $stdout for output\n";
|
||||
|
||||
chdir $params{TEMPDIR} || die "Could not cd $params{TEMPDIR}: $!\n";
|
||||
system $preCmd;
|
||||
close STDOUT;
|
||||
open STDOUT, ">&SAVEOUT";
|
||||
printf "Test done.\n";
|
||||
|
||||
chdir $cwd || die "Could not cd $cwd: $!\n";
|
||||
last; # only do the first one
|
||||
}
|
||||
} else { # not NT (forking works)
|
||||
|
||||
foreach $section (@workload) { # do pre run commands
|
||||
next unless ($section->{sectionTitle} =~ /PRETEST/o);
|
||||
unless ($section->{COMMAND}) {
|
||||
print "PreTest with no Command for $section->{sectionParams}\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my $myCmd = $section->{COMMAND};
|
||||
$myCmd =~ s/%f/$params{FREQUENCY}/; # fill in frequency variable
|
||||
if ($myCmd =~ m/%c/o) { # dont force down if count is used
|
||||
$count = $testsecs / $params{FREQUENCY};
|
||||
$myCmd =~ s/%c/$count/; # fill in count variable
|
||||
}
|
||||
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
|
||||
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
print "Running pre test command on $cli\n";
|
||||
open PRE, ">>$resultdir/$cli-pre.log";
|
||||
print PRE "========\n";
|
||||
print PRE "$myCmd\n";
|
||||
print PRE "========\n";
|
||||
close PRE;
|
||||
print STDERR "$cli: $myCmd\n"; # log the actual command
|
||||
forkproc ($rsh, $cli, $myCmd,
|
||||
"/dev/null", "$resultdir/$cli-pre.log");
|
||||
}
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
wait(); # run multiple PRETEST section sequentially
|
||||
}
|
||||
}
|
||||
|
||||
foreach $section (@workload) { # start monitors
|
||||
next unless ($section->{sectionTitle} =~ /MONITOR/o);
|
||||
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my $myCmd = ($section->{COMMAND})
|
||||
? $section->{COMMAND} : $params{MONITORCOMMAND};
|
||||
my $forceDown = 0;
|
||||
$myCmd =~ s/,/ /g; # turn commas into spaces BACK COMPATIBIILITY
|
||||
$myCmd =~ s/%f/$params{FREQUENCY}/; # fill in frequency variable
|
||||
|
||||
if ($myCmd =~ m/%c/o) { # dont force down if count is used
|
||||
$count = $testsecs / $params{FREQUENCY};
|
||||
$myCmd =~ s/%c/$count/; # fill in count variable
|
||||
} else {
|
||||
$forceDown = 1;
|
||||
}
|
||||
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
|
||||
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
printf "Monitoring on $cli\n";
|
||||
open PRE, ">>$resultdir/$cli-run.log";
|
||||
print PRE "========\n";
|
||||
print PRE "$myCmd\n";
|
||||
print PRE "========\n";
|
||||
close PRE;
|
||||
print STDERR "$cli: $myCmd\n"; # log the actual command
|
||||
$pid = forkproc ($rsh, $cli, $myCmd,
|
||||
"/dev/null", "$resultdir/$cli-run.log");
|
||||
push @forceDownPids, $pid if ($forceDown); # save PID for shutdown
|
||||
}
|
||||
}
|
||||
|
||||
print "Starting clients (errors logged to $resultdir/stderr)\n";
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
next unless ($section->{PROCESSES}); # unused client
|
||||
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
|
||||
my $pcount = $section->{PROCESSES};
|
||||
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 0;
|
||||
my $tempdir;
|
||||
if ($section->{TEMPDIR}) {
|
||||
$tempdir = $section->{TEMPDIR};
|
||||
} elsif ($params{TEMPDIR}) {
|
||||
$tempdir = $params{TEMPDIR};
|
||||
}
|
||||
my $preCmd = "./" . (($section->{COMMAND})
|
||||
? $section->{COMMAND} : $params{CLIENTCOMMAND});
|
||||
$preCmd .= " -s -t $params{TIME} -f $params{FREQUENCY}";
|
||||
$preCmd .= " -d" if ($params{DEBUG});
|
||||
$preCmd .= " -r" if ($params{TELEMETRY});
|
||||
$preCmd .= " -R $params{RAMPTIME}" if ($params{RAMPTIME});
|
||||
if ($params{MAXERRORS}) {
|
||||
# distribute error count over processes, rounding up
|
||||
my $n = int (($params{MAXERRORS} + $clientProcCount - 1)
|
||||
/ $clientProcCount);
|
||||
$n = 1 if ($n < 1);
|
||||
$preCmd .= " -m $n";
|
||||
}
|
||||
if ($params{MAXBLOCKS}) {
|
||||
# distribute block count over processes, rounding up
|
||||
my $n = int (($params{MAXBLOCKS} + $clientProcCount - 1)
|
||||
/ $clientProcCount);
|
||||
$n = 1 if ($n < 1);
|
||||
$preCmd .= " -M $n";
|
||||
}
|
||||
$preCmd = "cd $tempdir; " . $preCmd if ($tempdir);
|
||||
$preCmd .= " -n $pcount";
|
||||
$preCmd =~ s!/!\\!g if ($section->{ARCH} eq "NT4.0");
|
||||
$preCmd =~ s/;/&&/g if ($section->{ARCH} eq "NT4.0");
|
||||
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
my $stdout = getClientFilename ($cli, $section);
|
||||
my $myCmd = $preCmd;
|
||||
$myCmd .= ($params{USEGROUPS} && $section->{GROUP})
|
||||
? " -H $section->{GROUP}" : " -H $cli";
|
||||
|
||||
if ($tcount) {
|
||||
$myCmd .= " -N $tcount";
|
||||
printf "Starting %d x %d on $cli\n", $pcount, $tcount;
|
||||
$totalProcs += $pcount * $tcount;
|
||||
} else {
|
||||
printf "Starting %d processes on $cli\n", $pcount;
|
||||
$totalProcs += $pcount;
|
||||
}
|
||||
|
||||
print STDERR "$cli: $myCmd\n"; # log the actual command
|
||||
$pid = forkproc ($rsh, $cli, $myCmd,
|
||||
"$resultdir/work.wld", $stdout);
|
||||
push @localPids, $pid if ($cli =~ /^localhost$/i);
|
||||
}
|
||||
}
|
||||
|
||||
if (@localPids) {
|
||||
# print "Trapping extraneous local signals\n";
|
||||
# This doesnt trap quite right. We dont die, but shell returns...
|
||||
$SIG{ALRM} = 'IGNORE'; # in case we get an ALRM from the mailclient
|
||||
}
|
||||
|
||||
printf "\nTest duration: %d %s. Rampup time: %d %s. Number of clients: %d\n",
|
||||
figureTimeNumber ($params{TIME}),
|
||||
figureTimeUnits ($params{TIME}, "seconds"),
|
||||
figureTimeNumber ($params{RAMPTIME}),
|
||||
figureTimeUnits ($params{RAMPTIME}, "seconds"),
|
||||
$totalProcs;
|
||||
|
||||
do 'makeindex.pl' || warn "$@\n"; # html index
|
||||
|
||||
print "Waiting for test to finish.\n";
|
||||
print "Waiting: ", scalar(localtime), "\n";
|
||||
# wait for children to finish
|
||||
$pid = wait();
|
||||
if (@forceDownPids) { # shut down after the first return.
|
||||
print "Shutting down @forceDownPids\n";
|
||||
kill 1 => @forceDownPids; # sigHUP
|
||||
# kill 9 => @forceDownPids; # sigTERM
|
||||
}
|
||||
while ($pid != -1) { # wait for all children
|
||||
$pid = wait();
|
||||
}
|
||||
|
||||
foreach $section (@workload) { # do post test commands
|
||||
next unless ($section->{sectionTitle} =~ /POSTTEST/o);
|
||||
unless ($section->{COMMAND}) {
|
||||
print "PostTest with no command for $section->{sectionParams}\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my $myCmd = $section->{COMMAND};
|
||||
$myCmd =~ s/%f/$params{FREQUENCY}/; # fill in frequency variable
|
||||
if ($myCmd =~ m/%c/o) { # dont force down if count is used
|
||||
$count = $testsecs / $params{FREQUENCY};
|
||||
$myCmd =~ s/%c/$count/; # fill in count variable
|
||||
}
|
||||
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
|
||||
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
printf "Running post test command on $cli\n";
|
||||
open PRE, ">>$resultdir/$cli-post.log";
|
||||
print PRE "========\n";
|
||||
print PRE "$myCmd\n";
|
||||
print PRE "========\n";
|
||||
close PRE;
|
||||
print STDERR "$cli: $myCmd\n"; # log the actual command
|
||||
forkproc ($rsh, $cli, $myCmd,
|
||||
"/dev/null", "$resultdir/$cli-post.log");
|
||||
}
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
wait(); # run multiple POSTTEST section sequentially
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print STDERR "\nDone.\n";
|
||||
close(STDERR);
|
||||
open STDERR, ">&SAVEERR";
|
||||
|
||||
print "\nClients done: ", scalar(localtime), "\n";
|
||||
print "Collecting results\n";
|
||||
|
||||
do 'reduce.pl' || die "$@\n"; # generate graphs and sums
|
||||
|
||||
print "Generating results pages\n";
|
||||
|
||||
do 'report.pl' || die "$@\n";
|
||||
|
||||
# Now display that data to console
|
||||
if ($params{VERBOSE}) {
|
||||
fileShow ($resultstxt);
|
||||
print "\n";
|
||||
}
|
||||
print "Processing done: ", scalar (localtime), "\n";
|
||||
|
||||
pathprint ("\nResults (text):\t$resultstxt\n");
|
||||
pathprint ( "Results (HTML):\t$resultshtml\n");
|
||||
print "Index of runs: \tfile://$cwd/$resultbase/index.html\n";
|
||||
|
||||
|
||||
# Now check for major problems in the stderr file
|
||||
if (open(RESULTSTXT, "$resultdir/stderr")) {
|
||||
$ERRCNT=0;
|
||||
while (<RESULTSTXT>) { $ERRCNT++; }
|
||||
close(RESULTSTXT);
|
||||
pathprint ("Error log ($ERRCNT lines):\t$resultdir/stderr\n");
|
||||
}
|
||||
|
||||
{ # list user requested logging
|
||||
my @logfiles = <$resultdir/*-pre.log>;
|
||||
if (@logfiles) {
|
||||
foreach $f (@logfiles) {
|
||||
print "Pre test log: \t$f\n";
|
||||
}
|
||||
}
|
||||
@logfiles = <$resultdir/*-run.log>;
|
||||
if (@logfiles) {
|
||||
foreach $f (@logfiles) {
|
||||
print "Monitoring log: \t$f\n";
|
||||
}
|
||||
}
|
||||
@logfiles = <$resultdir/*-post.log>;
|
||||
if (@logfiles) {
|
||||
foreach $f (@logfiles) {
|
||||
print "Post test log: \t$f\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "Mailmaster done: ", scalar(localtime), "\n"; exit 0;
|
|
@ -1,115 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Mailstone utility,
|
||||
# released March 17, 2000.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
# Marcel DePaolis <marcel@netcape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
#####################################################
|
||||
|
||||
# usage: perl -Ibin makeindex.pl
|
||||
# Look at all the results files and create a top level index
|
||||
|
||||
unless ($resultbase) { # pick up systematic defaults, if needed
|
||||
do 'args.pl'|| die $@;
|
||||
parseArgs(); # parse command line
|
||||
}
|
||||
|
||||
($testname = $params{WORKLOAD}) =~ s:conf/::;
|
||||
$testname =~ s:.wld::;
|
||||
|
||||
my $entry = "";
|
||||
|
||||
$entry .= "<TR><TD><BR><A HREF=\"$params{TSTAMP}/results.html\">$params{TSTAMP}</A></TD>";
|
||||
$entry .= "<TD>$testname</TD>\n";
|
||||
$entry .= "<TD>$params{TITLE}</TD>\n";
|
||||
$entry .= "<TD>$params{TIME}</TD>\n";
|
||||
$entry .= "<TD>$params{CLIENTCOUNT}</TD>\n";
|
||||
$entry .= "<TD><A HREF=\"$params{TSTAMP}/all.wld\">workload</A></TD>\n";
|
||||
$entry .= "<TD><A HREF=\"$params{TSTAMP}/stderr\">stderr</A></TD></TR>\n";
|
||||
|
||||
if (-r "$resultbase/index.html") {
|
||||
fileInsertAfter ("$resultbase/index.html",
|
||||
"^<!-- INSERT TAGS HERE",
|
||||
$entry);
|
||||
} else { # create index from scratch
|
||||
system ("cd $resultbase; ln -s ../doc .");
|
||||
open(INDEXNEW, ">$resultbase/index.new") ||
|
||||
die "Couldn't open $resultbase/index.new: $!";
|
||||
|
||||
print INDEXNEW <<END;
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<TITLE>
|
||||
MailStone Results
|
||||
</TITLE>
|
||||
<HEAD>
|
||||
</HEAD>
|
||||
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#FF0000" ALINK="#000088">
|
||||
<A HREF=$mailstoneURL>Mailstone documentation</A><BR>
|
||||
<TABLE BORDER=2>
|
||||
<CAPTION> Netscape MailStone Results Index </CAPTION>
|
||||
<TR>
|
||||
<TH>Run</TH> <TH>Testname</TH> <TH> Title </TH>
|
||||
<TH>Duration</TH> <TH>Clients</TH> <TH>Details</TH> <TH>Error log</TH>
|
||||
</TR>
|
||||
<!-- INSERT TAGS HERE - DO NOT DELETE THIS LINE -->
|
||||
END
|
||||
|
||||
print INDEXNEW $entry; # put in this entry
|
||||
|
||||
# Add in any existing entries
|
||||
# get a list of all the results files
|
||||
@resall = <$resultbase/*/results.html>;
|
||||
# Write out all the links
|
||||
# This could be rather slow, but we only do it when index.html is missing
|
||||
foreach $filefull (reverse @resall) {
|
||||
my $file = $filefull;
|
||||
$file =~ s:$resultbase/::;
|
||||
if ($file eq $params{TSTAMP}) { next; } # written above
|
||||
my $dir = $file;
|
||||
$dir =~ s:/results.html::;
|
||||
# dont read in old workloads, it will override the current one
|
||||
print INDEXNEW "<TR><TD><BR><A HREF=\"$file\">$dir</A></TD>\n";
|
||||
print INDEXNEW "<TD> </TD><TD> </TD><TD> </TD><TD> </TD>\n";
|
||||
print INDEXNEW "<TD><A HREF=\"$dir/all.wld\">workload</A></TD>\n";
|
||||
print INDEXNEW "<TD><A HREF=\"$dir/stderr\">stderr</A></TD></TR>\n";
|
||||
}
|
||||
|
||||
print INDEXNEW <<END;
|
||||
</TABLE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
END
|
||||
close (INDEXNEW);
|
||||
fileBackup ("$resultbase/index.html");
|
||||
rename ("$resultbase/index.new", "$resultbase/index.html");
|
||||
print "Created $resultbase/index.html\n";
|
||||
}
|
||||
|
||||
return 1;
|
|
@ -1,414 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Mailstone utility,
|
||||
# released March 17, 2000.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
# Marcel DePaolis <marcel@netcape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
#####################################################
|
||||
|
||||
# script to create test user accounts for Netscape Messaging Server 3, 4
|
||||
#
|
||||
# Given a set of parameters, this script will create an LDIF file
|
||||
# for a number of email users of the form:
|
||||
# test1, test2, test3, ...
|
||||
#
|
||||
# usage: perl create_accounts_ldif [users] [broadcast] [postmaster] [ options ]
|
||||
# [ -a allUsersAlias ]
|
||||
# [ -b basedn ]
|
||||
# [ -d maildomain ]
|
||||
# [ -f firstaccount ]
|
||||
# [ -k ]
|
||||
# [ -m mailhost ]
|
||||
# [ -n numaccounts ]
|
||||
# [ -o outputfile ]
|
||||
# [ -p password ]
|
||||
# [ -s storebase ]
|
||||
# [ -u username ]
|
||||
# [ -v ]
|
||||
# [ -w workload ]
|
||||
# [ -x maxstores ]
|
||||
# [ -3 ]
|
||||
#
|
||||
#perl -Ibin -- bin/makeusers.pl -d mailhost.example.com -m mailhost.example.com -b 'o=example.com' -u mailhost-test -n 100 -4 -o mailhost100.ldif
|
||||
|
||||
# Create the ldif for the user accounts and/or broadcast, postmaster account.
|
||||
#
|
||||
# The ldif then must be added to
|
||||
# the directory by hand (ldapadd, or through the dir admin server's
|
||||
# Database Mgmt->Add entries from an ldif file).
|
||||
|
||||
# A faster way
|
||||
# is to export the existing directory, append the results of
|
||||
# this script, and re-import the combined file. This can be
|
||||
# done using the following Netscape Directory Server commands:
|
||||
# stop-slapd
|
||||
# db2ldif outputfile
|
||||
# [ merge files ]
|
||||
# ldif2db inputfile # for DS4 you would typically use -noconfig
|
||||
# start-sladp
|
||||
#
|
||||
|
||||
print "Netscape Mailstone.\nCopyright (c) 1998,1999 Netscape Communications Corp.\n";
|
||||
|
||||
# server to be used in the internet mail address of the users
|
||||
$domain = "newdomain.example.net";
|
||||
|
||||
# machine that will act as the user's mailhost
|
||||
$mailhost = "mailhost.example.net";
|
||||
|
||||
# base dn for the user entries, e.g. o=Ace Industry,c=US
|
||||
$basedn = "o=Benchmark Lab, c=US";
|
||||
|
||||
# name of broadcast account
|
||||
$bcastacct = "allusers";
|
||||
|
||||
# name of broadcast account
|
||||
$postmasteraddr = "root\@localhost";
|
||||
|
||||
# base name to build user names, will construct test0, test1, ...
|
||||
$username = "test%ld";
|
||||
|
||||
# user passwds, in SHA format, the passwd below is 'netscape'
|
||||
#$userpassword = "{SHA}aluWfd0LYY9ImsJb3h4afrI4AXk=";
|
||||
# these can also be imported as cleartext
|
||||
$userpassword = "netscape";
|
||||
|
||||
# 0: no numbered passwords, 1: number with userID
|
||||
$maxpass = 0;
|
||||
|
||||
# first account to use
|
||||
$firstaccount = 0;
|
||||
|
||||
# number of user accounts to create ($first - $first+$num-1)
|
||||
$numaccounts = 1_000;
|
||||
|
||||
# For larger systems, spreading the users over multiple partitions
|
||||
# is usually a good idea. This example assumes you have
|
||||
# created partitions named p0, p1, etc.
|
||||
|
||||
# store partition base name
|
||||
$storebase = "p%ld";
|
||||
|
||||
# max store number (0 - maxstores-1), skip if 0
|
||||
$maxstores = 0;
|
||||
|
||||
#default to msg 4 schemas
|
||||
$usemsg4schema = 1;
|
||||
|
||||
#default to writing to stdout
|
||||
$outfile = STDOUT;
|
||||
|
||||
# Initial UID for genpasswd
|
||||
$firstuid = 1000;
|
||||
|
||||
sub usage {
|
||||
print "Usage: perl -Ibin -- makeusers [users] [broadcast] [postmaster]\n";
|
||||
print "\t[ -w workload ] [ -o outputFile ]\n";
|
||||
print "\t[ -d mailDomain ] [ -m mailHost ] [ -b baseDN ]\n";
|
||||
print "\t[ -u username ] [ -f firstAccount ] [ -n numAccounts ]\n";
|
||||
print "\t[ -p password ] [ -k ]\n";
|
||||
print "\t[ -s storeBase ] [ -x numStores ]\n";
|
||||
print "\t[ -a allUsersAlias ] [ -t postmasterAddress ]\n";
|
||||
print "\t[ -3 ]|[ -4 ]\n";
|
||||
}
|
||||
|
||||
sub readWorkConfig { # read the workload in, parse our params
|
||||
my $workloadfile = shift || die "Workload file name expected\n";
|
||||
|
||||
do 'args.pl'|| die $@;
|
||||
readWorkloadFile ($workloadfile, \@workload)
|
||||
|| die "Error reading workload: $@\n";
|
||||
# assign all the parameters from the config
|
||||
$mailhost = $defaultSection->{SERVER}
|
||||
if ($defaultSection->{SERVER});
|
||||
if ($defaultSection->{ADDRESSFORMAT}) {
|
||||
my $addr = $defaultSection->{ADDRESSFORMAT};
|
||||
$addr =~ s/^.*@//;
|
||||
$domain = $addr;
|
||||
}
|
||||
if ($defaultSection->{LOGINFORMAT}) {
|
||||
my $user = $defaultSection->{LOGINFORMAT};
|
||||
#$user =~ s/%ld$//;
|
||||
$username = $user;
|
||||
}
|
||||
$numaccounts = $defaultSection->{NUMLOGINS}
|
||||
if ($defaultSection->{NUMLOGINS});
|
||||
$firstaccount = $defaultSection->{FIRSTLOGINS}
|
||||
if ($defaultSection->{FIRSTLOGINS});
|
||||
|
||||
$userpassword = $defaultSection->{PASSWDFORMAT}
|
||||
if ($defaultSection->{SERVER});
|
||||
|
||||
if ($userpassword =~ m/%ld/) { # see if numbered passwords
|
||||
$maxpass++;
|
||||
#$userpassword =~ s/%ld//g;
|
||||
}
|
||||
|
||||
# what isnt set: basedn, storebase, maxstores, usemsg4schema
|
||||
}
|
||||
|
||||
while (@ARGV) {
|
||||
$arg = shift(@ARGV);
|
||||
|
||||
if ($arg =~ /^-a$/i) { # allusers (broadcast) user name
|
||||
$bcastacct = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-b$/i) { # LDAP base DN
|
||||
$basedn = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-d$/i) { # mail domain
|
||||
$domain = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-f$/i) { # initial account
|
||||
$firstaccount = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-k$/i) { # use numbered passwords
|
||||
$maxpass++;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-h$/i) { # help
|
||||
usage();
|
||||
exit 0;
|
||||
}
|
||||
if ($arg =~ /^-m$/i) { # mail server name
|
||||
$mailhost = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-n$/i) { # number of accounts
|
||||
$numaccounts = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-o$/i) { # name output file
|
||||
my $fname = shift || die "File name expected\n";
|
||||
open OUTFILE, ">$fname" || die "Error opening file $@\n";
|
||||
$outfile = OUTFILE;
|
||||
next; # use msg4 user admin schema
|
||||
}
|
||||
if ($arg =~ /^-p$/i) { # password
|
||||
$userpassword = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-s$/i) { # base name for above
|
||||
$storebase = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-t$/i) { # postmaster address
|
||||
$postmasteraddress = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-u$/i) { # user name base
|
||||
$username = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-v$/i) { # be verbose
|
||||
$verbose++;
|
||||
next;
|
||||
}
|
||||
# do this when read, so that later switches can override
|
||||
if ($arg =~ /^-w$/i) { # get a workload file
|
||||
readWorkConfig (shift(@ARGV));
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-x$/i) { # number of partitions (0 to skip)
|
||||
$maxstores = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-3$/) { # no msg4 schema
|
||||
$usemsg4schema = 0;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^-4$/) { # use msg4 user admin schema
|
||||
$usemsg4schema = 1;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^users$/i) {
|
||||
$genusers++;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^broadcast$/i) {
|
||||
$genbroadcast++;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^passwd$/i) {
|
||||
$genpasswd++;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^postmaster$/i) {
|
||||
$genpostmaster++;
|
||||
next;
|
||||
}
|
||||
|
||||
print STDERR "Unknown argument $arg. Use -h for help.\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
unless (($genusers) || ($genbroadcast) || ($genpasswd) || ($genpostmaster)) {
|
||||
print STDERR "Must specify mode [users] [broadcast] [postmaster] ...\n";
|
||||
usage();
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# specify number fields, if needed
|
||||
unless ($username =~ /%ld/) {
|
||||
$username .= '%ld';
|
||||
}
|
||||
if (($maxpass) && !($userpassword =~ /%ld/)) {
|
||||
$userpassword .= '%ld';
|
||||
}
|
||||
if (($maxstores) && !($storename =~ /%ld/)) {
|
||||
$storename .= '%ld';
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
print STDERR "Here is the configuration:\n";
|
||||
print STDERR "baseDN='$basedn' \t";
|
||||
print STDERR (($usemsg4schema) ? "-4\n" : "-3\n");
|
||||
print STDERR "mailHost='$mailhost' \tdomain='$domain'\n";
|
||||
print STDERR "userName='$username' \tnumAccounts=$numaccounts \tfirstAccount=$firstaccount\n";
|
||||
print STDERR "userPassword='$userpassword'\n";
|
||||
print STDERR "allUsersAccount='$bcastacct'\n" if ($genbroadcast);
|
||||
print STDERR "postmasterAddress='$postmasterAddress'\n" if ($genpostmaster);
|
||||
}
|
||||
|
||||
|
||||
if ($genusers) { # Create the user accounts
|
||||
$storenum=0;
|
||||
for ($i = $firstaccount; $i < $firstaccount+$numaccounts; $i++) {
|
||||
# build user account name
|
||||
my $acctname = $username;
|
||||
$acctname =~ s/%ld/$i/; # insert user number
|
||||
my $password = $userpassword;
|
||||
$password =~ s/%ld/$i/; # insert user number
|
||||
|
||||
|
||||
|
||||
# MAKE SURE THERE ARE NO TRAILING SPACES IN THE LDIF
|
||||
my $extradata = "";
|
||||
|
||||
if ($maxstores > 0) { # assign them to a store
|
||||
my $storename = $storebase;
|
||||
$storename =~ s/%ld/$storenum/;
|
||||
$extradata .= "mailmessagestore: $storename\n";
|
||||
$storenum++;
|
||||
$storenum=0 if ($storenum >= $maxstores);
|
||||
}
|
||||
|
||||
$extradata .= "objectclass: nsMessagingServerUser\n"
|
||||
if ($usemsg4schema);
|
||||
|
||||
print $outfile <<END;
|
||||
dn: uid=$acctname, $basedn
|
||||
userpassword: $password
|
||||
givenname: $acctname
|
||||
sn: $acctname
|
||||
cn: $acctname
|
||||
uid: $acctname
|
||||
mail: $acctname\@$domain
|
||||
mailhost: $mailhost
|
||||
maildeliveryoption: mailbox
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
objectclass: mailRecipient
|
||||
$extradata
|
||||
END
|
||||
}
|
||||
}
|
||||
|
||||
if ($genbroadcast) { # Create the broadcast account
|
||||
# MAKE SURE THERE ARE NO TRAILING SPACES IN THE LDIF
|
||||
my $password = $userpassword;
|
||||
$password =~ s/%ld//; # strip user number
|
||||
# initial part
|
||||
print $outfile <<END;
|
||||
dn: uid=$bcastacct, $basedn
|
||||
userpassword: $password
|
||||
givenname: $bcastacct
|
||||
sn: $bcastacct
|
||||
cn: $bcastacct
|
||||
uid: $bcastacct
|
||||
mail: $bcastacct\@$domain
|
||||
mailhost: $mailhost
|
||||
maildeliveryoption: forward
|
||||
END
|
||||
|
||||
# now put in each address
|
||||
for ($i = $firstaccount; $i < $firstaccount+$numaccounts; $i++) {
|
||||
# build user account name
|
||||
my $acctname = $username;
|
||||
$acctname =~ s/%ld/$i/; # insert user number
|
||||
|
||||
print $outfile "mailforwardingaddress: $acctname\@$domain\n";
|
||||
}
|
||||
|
||||
# final part
|
||||
print $outfile <<END;
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
objectclass: mailRecipient
|
||||
|
||||
END
|
||||
}
|
||||
|
||||
if ($genpostmaster) { # Create the postmaster account
|
||||
# MAKE SURE THERE ARE NO TRAILING SPACES IN THE LDIF
|
||||
print $outfile <<END;
|
||||
dn: cn=postmaster, $basedn
|
||||
cn: postmaster
|
||||
mail: postmaster\@$domain
|
||||
mailalternateaddress: postmaster\@$mailhost
|
||||
mgrprfc822mailmember: $postmasterAddress
|
||||
objectclass: top
|
||||
objectclass: mailGroup
|
||||
objectclass: groupOfUniqueNames
|
||||
|
||||
END
|
||||
}
|
||||
|
||||
# mixing passwd output with the ldif output above would be quite silly
|
||||
if ($genpasswd) { # Create passwd entries for makeusers
|
||||
for ($i = $firstaccount; $i < $firstaccount+$numaccounts; $i++) {
|
||||
# build user account name
|
||||
my $acctname = $username;
|
||||
$acctname =~ s/%ld/$i/; # insert user number
|
||||
my $password = $userpassword;
|
||||
$password =~ s/%ld/$i/; # insert user number
|
||||
my $uid = $firstuid + $i;
|
||||
print $outfile "$acctname:$password:$uid:$uid:Mail user $acctname:/home/$acctname:/bin/sh\n";
|
||||
}
|
||||
}
|
||||
|
||||
exit 0;
|
|
@ -1,158 +0,0 @@
|
|||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Mailstone utility,
|
||||
# released March 17, 2000.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
# Marcel DePaolis <marcel@netcape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
#####################################################
|
||||
|
||||
# This define the structures that hold summary, client, and graph data,
|
||||
|
||||
# This sets the names used for display. Can be internationalized.
|
||||
# All top level names are here (both timers and scalars).
|
||||
# Any unlisted names will map to themselves.
|
||||
%timerNames
|
||||
= (
|
||||
#internal name, Printed name
|
||||
"total", "total",
|
||||
"conn", "connect",
|
||||
"reconn", "reconnect",
|
||||
"banner", "banner",
|
||||
"login", "login",
|
||||
"cmd", "command",
|
||||
"submit", "submit",
|
||||
"retrieve", "retrieve",
|
||||
"logout", "logout",
|
||||
"idle", "idle",
|
||||
"connections", "connections",
|
||||
"blocks", "blocks",
|
||||
);
|
||||
|
||||
# This sets the names used for display. Can be internationalized.
|
||||
%fieldNames
|
||||
= (
|
||||
#internal name, Printed name
|
||||
"Try", "Try",
|
||||
"Error", "Error",
|
||||
"BytesR", "BytesR",
|
||||
"BytesW", "BytesW",
|
||||
"Time", "Time",
|
||||
"TimeMin", "TMin",
|
||||
"TimeMax", "TMax",
|
||||
"Time2", "TStd",
|
||||
);
|
||||
|
||||
|
||||
# hold time graphs for each protocol
|
||||
%graphs = ();
|
||||
|
||||
# Totals are done during plotting, if needed
|
||||
%finals = (); # create base finals hash
|
||||
|
||||
# These are sections that dont get passed to mailclient (case insensitive)
|
||||
@scriptWorkloadSections
|
||||
= (
|
||||
"Config", # special, references %params
|
||||
"Client", # testbed client(s)
|
||||
"Graph", # graph generation
|
||||
"Setup", # things to run with ./setup
|
||||
"Startup", # things to run before test
|
||||
"Monitor", # other performance monitoring
|
||||
"PreTest", # things to run before test
|
||||
"PostTest", # things to run after test
|
||||
);
|
||||
|
||||
# These are sections that arent protocols. Anything else must be.
|
||||
@nonProtocolSections
|
||||
= (@scriptWorkloadSections, ("Default"));
|
||||
|
||||
# These are the known workload parameters (as they will print)
|
||||
# These are coerced to upper case internally (do NOT internationize)
|
||||
@workloadParameters
|
||||
= (
|
||||
"addressFormat",
|
||||
"arch",
|
||||
"blockID",
|
||||
"blockTime",
|
||||
"chartHeight",
|
||||
"chartPoints",
|
||||
"chartWidth",
|
||||
"clientCount",
|
||||
"command",
|
||||
"comments",
|
||||
"file",
|
||||
"firstAddress",
|
||||
"firstLogin",
|
||||
"frequency",
|
||||
"gnuplot",
|
||||
"group",
|
||||
"idleTime",
|
||||
"leaveMailOnServer",
|
||||
"loginFormat",
|
||||
"loopDelay",
|
||||
"numAddresses",
|
||||
"numLogins",
|
||||
"numLoops",
|
||||
"numRecips",
|
||||
"mailClient",
|
||||
"maxBlocks",
|
||||
"maxClients",
|
||||
"maxErrors",
|
||||
"maxThreads",
|
||||
"maxProcesses",
|
||||
"passwdFormat",
|
||||
"processes",
|
||||
"rampTime",
|
||||
"rcp",
|
||||
"rsh",
|
||||
"sequentialAddresses",
|
||||
"sequentialLogins",
|
||||
"server",
|
||||
"smtpMailFrom",
|
||||
"sysConfig",
|
||||
"threads",
|
||||
"telemetry",
|
||||
"tempDir",
|
||||
"time",
|
||||
"title",
|
||||
"TStamp",
|
||||
"useAuthLogin",
|
||||
"useEHLO",
|
||||
"weight",
|
||||
"wmapBannerCmds",
|
||||
"wmapClientHeader",
|
||||
"wmapInBoxCmds",
|
||||
"wmapLoginCmd",
|
||||
"wmapLoginData",
|
||||
"wmapLogoutCmds",
|
||||
"wmapMsgReadCmds",
|
||||
"wmapMsgWriteCmds",
|
||||
"workload",
|
||||
);
|
||||
|
||||
return 1;
|
1058
mstone/bin/reduce.pl
1058
mstone/bin/reduce.pl
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,605 +0,0 @@
|
|||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Mailstone utility,
|
||||
# released March 17, 2000.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
# Marcel DePaolis <marcel@netcape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
#####################################################
|
||||
|
||||
# This file deals with the summary data only
|
||||
|
||||
# Should be packages
|
||||
do 'genplot.pl' || die "$@\n";
|
||||
|
||||
sub walkSetupTotals {
|
||||
my $a = shift; my $f = shift; my $p = shift;
|
||||
if ($p =~ /(\w+):(\w+):$/) {
|
||||
my $tm = $2;
|
||||
if (!($finals{Total}->{$tm}->{$f})) {
|
||||
$finals{Total}->{$tm}->{$f} = $a;
|
||||
} elsif ($f =~ /Min$/) {
|
||||
$finals{Total}->{$tm}->{$f} = $a
|
||||
if (($a > 0.0) && ($a < $finals{Total}->{$tm}->{$f}));
|
||||
} elsif ($f =~ /Max$/) {
|
||||
$finals{Total}->{$tm}->{$f} = $a if ($a > $finals{Total}->{$tm}->{$f});
|
||||
} else {
|
||||
$finals{Total}->{$tm}->{$f} += $a;}
|
||||
}
|
||||
elsif ($p =~ /(\w+):$/) {
|
||||
$finals{Total}->{$f} += $a;
|
||||
}
|
||||
}
|
||||
|
||||
sub setupTotals {
|
||||
# Figure out combined timers for "Total" protocol
|
||||
# We might do a smarter merge here (look at context and try to match order)
|
||||
# As long as the first protocol is a superset, it wont matter
|
||||
my @tnames;
|
||||
foreach $proto (@protocols) {
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n;
|
||||
$t =~ s/([][{}*+?^.\/])/\\$1/g; # quote regex syntax
|
||||
my $found = 0;
|
||||
foreach $tn (@tnames) { # see if it is in the list already
|
||||
next unless ($tn =~ /$t/);
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
#print "proto $proto: Found $n\n" if ($found > 0);
|
||||
next if ($found > 0);
|
||||
#print "proto $proto: Add $n\n";
|
||||
push @tnames, $n; # add to list
|
||||
}
|
||||
}
|
||||
#print "'Total' timers @tnames\n";
|
||||
$protocolFields{"Total"} = \@tnames;
|
||||
|
||||
# Create "Total" hashes
|
||||
$finals{Total} = ArrayInstance->new();
|
||||
foreach $n (@{$protocolFields{"Total"}}) { # all timers
|
||||
my $t = $n; # dont modify original list
|
||||
if ($t =~ /^\[(\w+)\]$/) { # Timer case, strip off brackets
|
||||
$finals{Total}->{$1} = ArrayInstance->new();
|
||||
#print "Creating Total timer field $1\n";
|
||||
} else { # scalar
|
||||
$finals{Total}->{$n} = 0;
|
||||
#print "Creating Total scalar field $n\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Total finals array
|
||||
foreach $proto (@protocols) {
|
||||
foreach $t (@{$protocolFields{$proto}}) {
|
||||
if ($t =~ /^\[(\w+)\]$/) { # Timer case, strip off brackets
|
||||
my $tm = $1;
|
||||
foreach $f (@timerFieldsAll) {
|
||||
my $a = $finals{$proto}->{$tm}->{$f};
|
||||
if (!($finals{Total}->{$tm}->{$f})) { # never touched
|
||||
$finals{Total}->{$tm}->{$f} = $a;
|
||||
} elsif ($f =~ /Min$/) {
|
||||
$finals{Total}->{$tm}->{$f} = $a
|
||||
if (($a > 0.0)
|
||||
&& ($a < $finals{Total}->{$tm}->{$f}));
|
||||
} elsif ($f =~ /Max$/) {
|
||||
$finals{Total}->{$tm}->{$f} = $a
|
||||
if ($a > $finals{Total}->{$tm}->{$f});
|
||||
} else {
|
||||
$finals{Total}->{$tm}->{$f} += $a;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$finals{Total}->{$t} += $finals{$proto}->{$t};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Convert Time2 to standard deviation
|
||||
foreach $proto (@protocolsAll) {
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n; # dont modify original list
|
||||
if ($t =~ /^\[(\w+)\]$/) { $t = $1; } # strip off brackets
|
||||
next unless ($finals{$proto}->{$t}); # proto doesnt have timer
|
||||
next unless ($finals{$proto}->{$t}->{Try});
|
||||
next unless ($finals{$proto}->{$t}->{Time2} > 0);
|
||||
my $ss = $finals{$proto}->{$t}->{Time2};
|
||||
my $tot = $finals{$proto}->{$t}->{Time};
|
||||
my $n = $finals{$proto}->{$t}->{Try};
|
||||
next unless ($n > 0); # skip if this is 0
|
||||
|
||||
my $var = ($ss - (($tot * $tot) / $n)) / $n;
|
||||
print "$proto->$t var < 0: Time2=$ss Time=$tot n=$n\n"
|
||||
if ($var < 0);
|
||||
$finals{$proto}->{$t}->{Time2} = ($var > 0) ? sqrt ($var) : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
# Divide total times by trys to get averate time
|
||||
foreach $proto (@protocolsAll) {
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n; # dont modify original list
|
||||
if ($t =~ /^\[(\w+)\]$/) { $t = $1; } # strip off brackets
|
||||
next unless ($finals{$proto}->{$t}); # proto doesnt have timer
|
||||
($finals{$proto}->{$t}->{Try}) || next;
|
||||
$finals{$proto}->{$t}->{Time} /= $finals{$proto}->{$t}->{Try}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# The text version is designed to be machine processable
|
||||
# commify and kformat are not used
|
||||
sub genTextReport {
|
||||
fileBackup ($resultstxt); # if processing as we go, backup old file
|
||||
# Open a text file to hold the results
|
||||
open(RESULTSTXT, ">$resultstxt") ||
|
||||
die "Couldn't open $resultstxt: $!";
|
||||
|
||||
# Store results as text
|
||||
printf RESULTSTXT "---- Netscape MailStone Results $params{TSTAMP} ----\n";
|
||||
|
||||
printf RESULTSTXT "\t\t%s\n", $params{TITLE};
|
||||
printf RESULTSTXT "\t\t%s\n", $params{COMMENTS};
|
||||
printf RESULTSTXT "\n";
|
||||
printf RESULTSTXT "Test duration: %d %s. Rampup: %d %s. Reported duration %s seconds\n",
|
||||
figureTimeNumber ($params{TIME}),
|
||||
figureTimeUnits ($params{TIME}, "minutes"),
|
||||
figureTimeNumber ($params{RAMPTIME}),
|
||||
figureTimeUnits ($params{RAMPTIME}, "seconds"), $realTestSecs;
|
||||
printf RESULTSTXT "Number of reporting clients: %s of %s\n",
|
||||
$reportingClients, $totalProcs;
|
||||
|
||||
foreach $proto (@protocolsAll) {
|
||||
# do op counters
|
||||
printf RESULTSTXT "\n%-15s ", $proto;
|
||||
foreach $f (@timerFieldsAll) {
|
||||
#($f =~ m/^Time2$/o) && next;
|
||||
printf RESULTSTXT "%13s",
|
||||
($fieldNames{$f}) ? $fieldNames{$f} : $f;
|
||||
}
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n; # dont modify original list
|
||||
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
|
||||
#next; # skip scalars for now
|
||||
# do scalar counters. Column should line up with "Try"
|
||||
printf RESULTSTXT "\n%-15s ",
|
||||
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t);
|
||||
printf RESULTSTXT
|
||||
"%13s", $finals{$proto}->{$t};
|
||||
next;
|
||||
} else { # strip off brackets
|
||||
$t = $1;
|
||||
}
|
||||
printf RESULTSTXT "\n%-15s ",
|
||||
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t);
|
||||
foreach $f (@timerFieldsAll) {
|
||||
#($f =~ m/^Time2$/o) && next;
|
||||
if ($f =~ m/Time/o) {
|
||||
printf RESULTSTXT
|
||||
"%13.3f", $finals{$proto}->{$t}->{$f};
|
||||
} elsif ($f =~ m/Bytes/o) {
|
||||
printf RESULTSTXT
|
||||
"%13d", $finals{$proto}->{$t}->{$f};
|
||||
} else {
|
||||
printf RESULTSTXT
|
||||
"%13s", $finals{$proto}->{$t}->{$f};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# do ops/sec
|
||||
printf RESULTSTXT "\n\n%-15s ", $proto;
|
||||
foreach $f (@timerFieldsAll) {
|
||||
($f =~ m/^Time/o) && next;
|
||||
printf RESULTSTXT "%9s/sec",
|
||||
($fieldNames{$f}) ? $fieldNames{$f} : $f;
|
||||
}
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n; # dont modify original list
|
||||
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
|
||||
#next; # skip scalars for now
|
||||
# do scalar counter/sec. Column should line up with "Try"
|
||||
printf RESULTSTXT "\n%-15s ",
|
||||
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t) . "/s";
|
||||
printf RESULTSTXT
|
||||
"%13.3f", $finals{$proto}->{$t} / $realTestSecs;
|
||||
next;
|
||||
} else {
|
||||
$t = $1;
|
||||
}
|
||||
printf RESULTSTXT "\n%-15s ",
|
||||
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t) . "/s";
|
||||
foreach $f (@timerFieldsAll) {
|
||||
($f =~ m/^Time/o) && next;
|
||||
if ($f =~ m/Bytes/o) {
|
||||
printf RESULTSTXT
|
||||
"%13d",
|
||||
$finals{$proto}->{$t}->{$f} / $realTestSecs;
|
||||
} else {
|
||||
printf RESULTSTXT
|
||||
"%13.3f",
|
||||
$finals{$proto}->{$t}->{$f} / $realTestSecs;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf RESULTSTXT "\n\n";
|
||||
}
|
||||
|
||||
if ($params{SYSCONFIG}) {
|
||||
print RESULTSTXT "\nSytem config details\n";
|
||||
if (($params{SYSCONFIG} =~ m/^\S+$/o)
|
||||
&& (open(SCFILE, "<$params{SYSCONFIG}"))) {
|
||||
while (<SCFILE>) {
|
||||
(m/^<\S+>\s*$/o) && next; # skip HTML only on them
|
||||
s/<\S+>//g; # trim out obvious HTML commands
|
||||
s/<!--.*-->//g; # trim out HTML comments
|
||||
print RESULTSTXT $_;
|
||||
}
|
||||
close(SCFILE);
|
||||
} else {
|
||||
my $l = $params{SYSCONFIG}; # filter similar to above
|
||||
$l =~ s/<\S+>//g; # trim out obvious HTML commands
|
||||
$l =~ s/<!--.*-->//g; # trim out HTML comments
|
||||
$l =~ s/\\\n/\n/g; # turn quoted newline to plain newline
|
||||
print RESULTSTXT $l;
|
||||
}
|
||||
}
|
||||
|
||||
close(RESULTSTXT);
|
||||
}
|
||||
|
||||
# Write the main part of the HTML page
|
||||
sub genHTMLReportStart {
|
||||
fileBackup ($resultshtml); # if processing as we go, backup old file
|
||||
# Open an html file to hold the results
|
||||
open(RESULTSHTML, ">$resultshtml") ||
|
||||
die "Couldn't open $resultshtml: $!";
|
||||
|
||||
print RESULTSHTML <<END;
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<A NAME=TitleSection>
|
||||
<TITLE>
|
||||
Netscape MailStone Results $params{TSTAMP}
|
||||
</TITLE>
|
||||
</A>
|
||||
<HEAD>
|
||||
</HEAD>
|
||||
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#FF0000" ALINK="#000088">
|
||||
<CENTER>
|
||||
<HR NOSHADE WIDTH="100%">
|
||||
<H1>Netscape MailStone Results $params{TSTAMP}</H1>
|
||||
<H2>$params{TITLE}</H2>
|
||||
<I>$params{COMMENTS}</I>
|
||||
<HR WIDTH="100%">
|
||||
</CENTER>
|
||||
|
||||
END
|
||||
printf RESULTSHTML "<BR><B>Test duration:</B> %d %s. ",
|
||||
figureTimeNumber ($params{TIME}),
|
||||
figureTimeUnits ($params{TIME}, "minutes");
|
||||
printf RESULTSHTML "<B>Rampup:</B> %d %s. ",
|
||||
figureTimeNumber ($params{RAMPTIME}),
|
||||
figureTimeUnits ($params{RAMPTIME}, "seconds");
|
||||
printf RESULTSHTML "<B>Reported duration:</B> %s seconds\n",
|
||||
commify ($realTestSecs);
|
||||
|
||||
printf RESULTSHTML "<BR><B>Reporting clients:</B> %s of %s\n",
|
||||
commify ($reportingClients), commify ($totalProcs);
|
||||
|
||||
print RESULTSHTML <<END;
|
||||
<BR>
|
||||
Test <A HREF="all.wld">complete workload</a> description.
|
||||
Filtered <A HREF="work.wld">workload</a> description.
|
||||
<BR>
|
||||
Plain <A HREF="results.txt">text version</a> of results.
|
||||
Log of <A HREF="stderr">stderr</a> and debugging output.
|
||||
<BR>
|
||||
|
||||
<A NAME=MonitoringSection></A>
|
||||
END
|
||||
|
||||
{ # list user requested logging
|
||||
my @logfiles = <$resultdir/*-pre.log>;
|
||||
if (@logfiles) {
|
||||
foreach $f (@logfiles) {
|
||||
$f =~ s/$resultdir\///o; # strip directory out
|
||||
$f =~ s/-pre\.log$//o; # strip extension off
|
||||
print RESULTSHTML "Pre test log: <A HREF=\"$f-pre.log\">$f</a><BR>\n";
|
||||
}
|
||||
}
|
||||
@logfiles = <$resultdir/*-run.log>;
|
||||
if (@logfiles) {
|
||||
foreach $f (@logfiles) {
|
||||
$f =~ s/$resultdir\///o; # strip directory out
|
||||
$f =~ s/-run\.log$//o; # strip extension off
|
||||
print RESULTSHTML "Monitoring log: <A HREF=\"$f-run.log\">$f</a><BR>\n";
|
||||
}
|
||||
}
|
||||
@logfiles = <$resultdir/*-post.log>;
|
||||
if (@logfiles) {
|
||||
foreach $f (@logfiles) {
|
||||
$f =~ s/$resultdir\///o; # strip directory out
|
||||
$f =~ s/-post\.log$//o; # strip extension off
|
||||
print RESULTSHTML "Post test log: <A HREF=\"$f-post.log\">$f</a><BR>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#print RESULTSHTML
|
||||
#"<CENTER><H2>Results per protocol</H2></CENTER>\n";
|
||||
|
||||
foreach $proto (@protocolsAll) {
|
||||
printf RESULTSHTML "<A NAME=%sTable></A>\n", $proto;
|
||||
printf RESULTSHTML
|
||||
"<TABLE BORDER=2 CELLSPACING=2 CELLPADDING=2 COLS=%d WIDTH=\"95%%\">",
|
||||
2+$#{@{$protocolFields{$proto}}};
|
||||
print RESULTSHTML
|
||||
"<CAPTION>$proto Counters</CAPTION>\n";
|
||||
# do op counters
|
||||
print RESULTSHTML
|
||||
"<TR><TH>$proto</TH>\n";
|
||||
foreach $f (@timerFieldsAll) {
|
||||
#($f =~ m/^Time2$/o) && next;
|
||||
printf RESULTSHTML "<TH>%s</TH> ",
|
||||
($fieldNames{$f}) ? $fieldNames{$f} : $f;
|
||||
}
|
||||
print RESULTSHTML
|
||||
"</TR>\n";
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n; # dont modify original list
|
||||
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
|
||||
next; # skip scalars for now
|
||||
# do scalar counters. Column should line up with "Try"
|
||||
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
|
||||
($timerNames{$t}) ? $timerNames{$t} : $t;
|
||||
printf RESULTSHTML
|
||||
"<TD>%s</TD> ",
|
||||
commify ($finals{$proto}->{$t});
|
||||
next;
|
||||
} else {
|
||||
$t = $1;
|
||||
}
|
||||
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
|
||||
($timerNames{$t}) ? $timerNames{$t} : $t;
|
||||
foreach $f (@timerFieldsAll) {
|
||||
#($f =~ m/^Time2$/o) && next;
|
||||
if ($f =~ m/Time/o) {
|
||||
printf RESULTSHTML
|
||||
"<TD>%s</TD> ",
|
||||
tformat ($finals{$proto}->{$t}->{$f});
|
||||
} elsif ($f =~ m/Bytes/o) {
|
||||
printf RESULTSHTML
|
||||
"<TD>%s</TD> ",
|
||||
kformat ($finals{$proto}->{$t}->{$f});
|
||||
} else {
|
||||
printf RESULTSHTML
|
||||
"<TD>%s</TD> ",
|
||||
commify ($finals{$proto}->{$t}->{$f});
|
||||
}
|
||||
}
|
||||
print RESULTSHTML "</TR>\n";
|
||||
}
|
||||
|
||||
# do ops/sec
|
||||
print RESULTSHTML
|
||||
"<TR><TH>$proto</TH>\n";
|
||||
foreach $f (@timerFieldsAll) {
|
||||
($f =~ m/^Time/o) && next;
|
||||
printf RESULTSHTML "<TH>%s/sec</TH> ",
|
||||
($fieldNames{$f}) ? $fieldNames{$f} : $f;
|
||||
}
|
||||
print RESULTSHTML
|
||||
"</TR>\n";
|
||||
foreach $n (@{$protocolFields{$proto}}) {
|
||||
my $t = $n; # dont modify original list
|
||||
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
|
||||
next; # skip scalars for now
|
||||
# do scalar counters. Column should line up with "Try"
|
||||
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
|
||||
($timerNames{$t}) ? $timerNames{$t} : $t;
|
||||
printf RESULTSHTML
|
||||
"<TD>%.3f</TD> ",
|
||||
$finals{$proto}->{$t} / $realTestSecs;
|
||||
next;
|
||||
} else {
|
||||
$t = $1;
|
||||
}
|
||||
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
|
||||
($timerNames{$t}) ? $timerNames{$t} : $t;
|
||||
foreach $f (@timerFieldsAll) {
|
||||
($f =~ m/^Time/o) && next;
|
||||
if ($f =~ m/Bytes/o) {
|
||||
printf RESULTSHTML
|
||||
"<TD>%s</TD> ",
|
||||
kformat ($finals{$proto}->{$t}->{$f} / $realTestSecs);
|
||||
} else {
|
||||
printf RESULTSHTML
|
||||
"<TD>%.3f</TD> ",
|
||||
$finals{$proto}->{$t}->{$f} / $realTestSecs;
|
||||
}
|
||||
}
|
||||
print RESULTSHTML "</TR>\n";
|
||||
}
|
||||
printf RESULTSHTML "</TABLE> <BR>\n\n";
|
||||
}
|
||||
|
||||
print RESULTSHTML <<END;
|
||||
|
||||
<BR>
|
||||
|
||||
<CENTER>
|
||||
<A NAME=GraphSection></A>
|
||||
END
|
||||
}
|
||||
|
||||
%genplotGraphs = ();
|
||||
|
||||
# Call genplot; and, if a graph is generated, insert the HTML reference to it
|
||||
sub genHTMLReportGraph {
|
||||
my $name = shift;
|
||||
my $title = shift;
|
||||
my $label = shift;
|
||||
my $protos = shift || die "genHTMLReportGraph: '$name' missing protocols";
|
||||
my $field = shift;
|
||||
my $vars = shift || die "genHTMLReportGraph: '$name' missing vars";
|
||||
|
||||
if ($genplotGraphs{$name}) {
|
||||
print "Graph $name has already been generated.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$genplotGraphs{$name} = $title;
|
||||
|
||||
# Delineate and tag each graph
|
||||
print RESULTSHTML "<A NAME=$name><HR SIZE=4 WIDTH=\"90%\"></A>\n";
|
||||
if (genPlot ($name, $title, $label, $protos, $field, $vars) > 0) {
|
||||
print RESULTSHTML <<END;
|
||||
<P><H3>$title</H3>
|
||||
<IMG SRC=$name.$params{IMAGETYPE} ALT="$label"></P>
|
||||
END
|
||||
} else {
|
||||
print RESULTSHTML "<BR>Graph \"$name\" contained no data (@{$vars}).<BR>\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Write the final parts of the HTML page
|
||||
sub genHTMLReportEnd {
|
||||
print RESULTSHTML <<END;
|
||||
<!-- INSERT IMAGES HERE - DO NOT DELETE THIS LINE -->
|
||||
</CENTER>
|
||||
<A NAME=EndSection></A>
|
||||
END
|
||||
|
||||
if ($params{SYSCONFIG}) {
|
||||
print RESULTSHTML "<HR WIDTH=\"100%\">";
|
||||
print RESULTSHTML "<CENTER><H2>Details</H2></CENTER>\n";
|
||||
if (($params{SYSCONFIG} =~ m/^\S+$/o)
|
||||
&& (open(SCFILE, "<$params{SYSCONFIG}"))) { # see if its a file
|
||||
while (<SCFILE>) {
|
||||
print RESULTSHTML $_;
|
||||
}
|
||||
close(SCFILE);
|
||||
} else { # output text directly
|
||||
my $l = $params{SYSCONFIG};
|
||||
$l =~ s/\\\n/\n/g; # turn quoted newline to plain newline
|
||||
print RESULTSHTML $l;
|
||||
}
|
||||
}
|
||||
|
||||
print RESULTSHTML <<END;
|
||||
|
||||
<HR NOSHADE WIDTH="100%">
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
END
|
||||
close(RESULTSHTML);
|
||||
}
|
||||
|
||||
|
||||
# Actually generate the standard stuff
|
||||
setupTotals();
|
||||
genTextReport();
|
||||
|
||||
|
||||
genHTMLReportStart();
|
||||
|
||||
my $graphCount = 0;
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /GRAPH/o);
|
||||
my $name = $section->{sectionParams};
|
||||
$name =~ s/name=\s*//; # strip off initial bit
|
||||
my @varlist = split (/[\s,]+/, $section->{VARIABLES});
|
||||
|
||||
$graphCount++;
|
||||
genHTMLReportGraph ($name, $section->{TITLE}, $section->{LABEL},
|
||||
($section->{FIELD} =~ /Time/o)
|
||||
? \@protocols : \@protocolsAll,
|
||||
$section->{FIELD}, \@varlist);
|
||||
}
|
||||
|
||||
if ($graphCount <= 0) { # use built ins
|
||||
|
||||
# generate the graphs we want
|
||||
# NOTE: the first argument (name), must be unique; sets file name
|
||||
genHTMLReportGraph ("connects",
|
||||
"Number of connections attempted", "Connections/sec",
|
||||
\@protocolsAll, "Try", ["conn" ]);
|
||||
genHTMLReportGraph ("connections",
|
||||
"Total connections", "Connections",
|
||||
\@protocolsAll, "", ["connections" ]);
|
||||
genHTMLReportGraph ("errors",
|
||||
"Number of connection errors", "Errors/sec",
|
||||
\@protocolsAll, "Error", ["conn", "banner", "login", "logout" ]);
|
||||
genHTMLReportGraph ("retrieves",
|
||||
"Number of messages read", "Messages/sec",
|
||||
\@protocolsAll, "Try", ["retrieve" ]);
|
||||
genHTMLReportGraph ("submits",
|
||||
"Number of messages written", "Messages/sec",
|
||||
\@protocolsAll, "Try", ["submit" ]);
|
||||
genHTMLReportGraph ("commands",
|
||||
"Protocol commands", "Commands/sec",
|
||||
\@protocolsAll, "Try", ["cmd" ]);
|
||||
genHTMLReportGraph ("readBytes",
|
||||
"Bytes read", "Bytes/sec",
|
||||
\@protocolsAll, "BytesR", ["login", "banner", "cmd", "retrieve", "submit", "logout" ]);
|
||||
genHTMLReportGraph ("writeBytes",
|
||||
"Bytes written", "Bytes/sec",
|
||||
\@protocolsAll, "BytesW", ["login", "banner", "cmd", "retrieve", "submit", "logout" ]);
|
||||
genHTMLReportGraph ("msgTime",
|
||||
"Message transfer time", "Seconds per message",
|
||||
\@protocols, "Time", ["cmd", "submit", "retrieve" ]);
|
||||
genHTMLReportGraph ("setupTime",
|
||||
"Connection setup time", "Seconds per connection",
|
||||
\@protocols, "Time", ["conn", "banner", "login" ]);
|
||||
genHTMLReportGraph ("blocks",
|
||||
"Number of mailstone blocks executed", "Blocks/sec",
|
||||
\@protocolsAll, "", ["blocks" ]);
|
||||
}
|
||||
|
||||
if ($params{ADDGRAPHS}) { # pick up additional graphs
|
||||
my @graphs = ();
|
||||
readWorkloadFile ($params{ADDGRAPHS}, \@graphs);
|
||||
foreach $section (@graphs) {
|
||||
next unless ($section->{sectionTitle} =~ /GRAPH/o);
|
||||
my $name = $section->{sectionParams};
|
||||
$name =~ s/name=\s*//; # strip off initial bit
|
||||
my @varlist = split (/[\s,]+/, $section->{VARIABLES});
|
||||
|
||||
$graphCount++;
|
||||
genHTMLReportGraph ($name, $section->{TITLE}, $section->{LABEL},
|
||||
($section->{FIELD} =~ /Time/o)
|
||||
? \@protocols : \@protocolsAll,
|
||||
$section->{FIELD}, \@varlist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
genHTMLReportEnd();
|
||||
|
||||
return 1;
|
|
@ -1,205 +0,0 @@
|
|||
#!/bin/ksh
|
||||
|
||||
# global configuration parameters.
|
||||
# Fill in defaults for anything that is not already set
|
||||
|
||||
# Look for testname$test_form, first
|
||||
export test_form=${test_form:-""}
|
||||
|
||||
# string appended to every description
|
||||
export desc_conf=${desc_conf:-""}
|
||||
|
||||
# extra arguments common to all tests
|
||||
export extra_args=${extra_args:-""}
|
||||
|
||||
# error limit to abort sequence
|
||||
export error_limit=${error_limit:-100}
|
||||
|
||||
# set this to only show what it will do
|
||||
export only_show_it=${only_show_it:-0}
|
||||
|
||||
# time to allow the server to calm down after each run
|
||||
export sleep_time=${sleep_time:-5}
|
||||
|
||||
# This is where we store the important runs
|
||||
export save_dir=${save_dir:-"results.save"}
|
||||
|
||||
# Basic sanity test
|
||||
if [[ ! -x /usr/bin/perl || ! -f .license ]] ; then # see if setup was ever run
|
||||
echo "Critical files are missing. Run setup."
|
||||
exit 2;
|
||||
fi
|
||||
|
||||
find_timestamp () { # find the timestamp string from latest run
|
||||
#OLD timestamp=`ls -d results/[0-9]*.[0-9][0-9][0-9][0-9]?(a-z) | tail -1`
|
||||
|
||||
# list all directories with the timestamp pattern
|
||||
timestamp=`echo results/[0-9]*.[0-9][0-9][0-9][0-9]?([a-z])`
|
||||
# strip all but the last one
|
||||
timestamp=${timestamp##* }
|
||||
|
||||
# strip the top directory name out
|
||||
timestamp=${timestamp#results/}
|
||||
|
||||
# return it
|
||||
echo $timestamp
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
# copy last mailstone run from the current directory to good results directory
|
||||
save_run () {
|
||||
|
||||
[[ -d $save_dir ]] || \
|
||||
mkdir $save_dir
|
||||
|
||||
[[ $only_show_it -gt 0 ]] && return 0 # dont do anything important
|
||||
|
||||
if [[ -n "$last_timestamp" && -d "results/$last_timestamp/" ]] ; then
|
||||
cp -pR results/$last_timestamp $save_dir/
|
||||
# index probably has lots of extra junk, but its better than nothing
|
||||
cp -pf results/index.html $save_dir/
|
||||
fi
|
||||
}
|
||||
|
||||
# Display and run a command. Skip if in only_show mode.
|
||||
run () {
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would run:" "$@"
|
||||
return 0
|
||||
fi
|
||||
echo "Running: " "$@"
|
||||
"$@"
|
||||
}
|
||||
|
||||
# Sleep. Skip if in only_show mode.
|
||||
run_sleep () {
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would sleep:" "$@"
|
||||
return 0
|
||||
fi
|
||||
echo "Sleeping: " "$@"
|
||||
sleep "$@"
|
||||
}
|
||||
# for readability, just use sleep
|
||||
alias sleep=run_sleep
|
||||
|
||||
|
||||
# This runs the actual mstone run and check for errors
|
||||
# compress tmp files
|
||||
# Usage: run_test testname description [args...]
|
||||
run_test () {
|
||||
testname="$1"; shift;
|
||||
desc="$1"; shift;
|
||||
|
||||
# see if a special version of this test exists
|
||||
if [[ -f conf/$testname$test_form.wld ]] ; then
|
||||
testname=$testname$test_form
|
||||
fi
|
||||
|
||||
#oldtimestamp=`find_timestamp`
|
||||
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would run:" mstone $testname -b "$desc $desc_conf" $extra_args "$@"
|
||||
if [[ ! -f conf/$testname.wld ]] ; then
|
||||
echo "Configuration Error: No such test $testname"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "\n##########################################################"
|
||||
if [[ ! -f conf/$testname.wld ]] ; then
|
||||
echo "CONFIGURATION ERROR: No such test $testname"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "\nRunning:" mstone $testname -b "$desc $desc_conf" $extra_args "$@"
|
||||
# We actually bypass the mstone script
|
||||
/usr/bin/perl -Ibin -- bin/mailmaster.pl -w conf/$testname.wld -b "$desc $desc_conf" $extra_args "$@"
|
||||
stat=$?
|
||||
|
||||
# BUG if another test is running at the same time, this is wrong
|
||||
timestamp="`find_timestamp`"
|
||||
|
||||
# test failed to even run
|
||||
if [[ $stat -ne 0 ]]
|
||||
then
|
||||
echo "ABORT! Test failed to start"
|
||||
[[ -n "$mail_list" ]] && \
|
||||
mail_series "DotCom Failed run: `date`" "$mail_list"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# compress tmp files. get the csv files, too.
|
||||
gzip tmp/$timestamp/* results/$timestamp/*.csv
|
||||
|
||||
# stick the timestamp someplace global for a save_run
|
||||
export last_timestamp=$timestamp
|
||||
export all_timestamps="$all_timestamps $timestamp"
|
||||
|
||||
# save the results
|
||||
save_run
|
||||
|
||||
# see how many errors we hit
|
||||
totline=`grep 'Total:total ' results/$timestamp/results.txt`
|
||||
|
||||
# strip label and first field
|
||||
errors=${totline##+([+-z])+( )+([+-9])+( )}
|
||||
# strip trailing fields
|
||||
errors=${errors%% *}
|
||||
|
||||
echo "" # space things out
|
||||
|
||||
if [[ $errors -gt $error_limit ]] ; then
|
||||
echo "ABORT! Errors ($errors) exceed error limit ($error_limit)"
|
||||
[[ -n "$mail_list" ]] && \
|
||||
mail_series "DotCom Aborted run: `date`" "$mail_list"
|
||||
exit 1
|
||||
fi
|
||||
echo "Run completed OK ($errors errors). Timestamp $timestamp"
|
||||
|
||||
sleep $sleep_time
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Usage: mail_series subject "address,address,..."
|
||||
mail_series () {
|
||||
subject=$1; shift
|
||||
file=/tmp/series$$.tar
|
||||
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would mail results about $subject" to "$@"
|
||||
return 0
|
||||
fi
|
||||
echo "Mailing results about $subject" to "$@"
|
||||
|
||||
tar cf $file $save_dir/index.html
|
||||
for f in $all_timestamps ; do
|
||||
tar rf $file $save_dir/$f
|
||||
done
|
||||
gzip $file
|
||||
echo "$all_timestamps" | uuenview -b -30000 -s "$subject" -m "$@" $file.gz
|
||||
rm -f $file.gz
|
||||
}
|
||||
|
||||
# parse command line arguments
|
||||
while [[ -n "$1" ]]
|
||||
do
|
||||
case $1 in
|
||||
# -n mode, do not execute, just show
|
||||
-n) only_show_it=1; shift;;
|
||||
|
||||
# set test form
|
||||
-f) shift; test_form=$1; shift;;
|
||||
|
||||
# set test extra description
|
||||
-d) shift; desc_conf=$1; shift;;
|
||||
|
||||
# Rest are to be passed in exactly
|
||||
--) shift; break;;
|
||||
|
||||
#default, pick up as an extra arg
|
||||
*) extra_args="$extra_args $1"; shift;;
|
||||
esac
|
||||
done
|
|
@ -1,417 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Mailstone utility,
|
||||
# released March 17, 2000.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1999-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
# Marcel DePaolis <marcel@netcape.com>
|
||||
# Jim Salter <jsalter@netscape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
#####################################################
|
||||
|
||||
# usage: setup.pl setup|cleanup|checktime|timesync -m machine_file
|
||||
# message files are expected to be in ./data/ and end with ".msg"
|
||||
|
||||
print "Netscape Mailstone.\nCopyright (c) 1997-2000 Netscape Communications Corp.\n";
|
||||
|
||||
$mode = shift; # mode must be first
|
||||
|
||||
# this parses the command line for -m machinefile
|
||||
# also sets many defaults
|
||||
do 'args.pl'|| die $@;
|
||||
parseArgs(); # parse command line
|
||||
|
||||
setConfigDefaults(); # setup RSH and RCP
|
||||
|
||||
$cpcmd = "cp"; # copy files... dir
|
||||
$rmcmd = "rm -f"; # remove files...
|
||||
|
||||
die "Must specify workload file" unless (@workload);
|
||||
|
||||
# Add or change client machines
|
||||
sub configClients {
|
||||
print "\n You can enter multiple machines like this: host1,host2\n";
|
||||
my @d = <bin/*/bin>;
|
||||
if (@d) {
|
||||
my @d2;
|
||||
foreach (@d2 = @d) { s/^bin\/// }
|
||||
foreach (@d = @d2) { s/\/bin$// }
|
||||
print " These OS versions are available:\n@d\n";
|
||||
}
|
||||
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
my $arch = "default OS";
|
||||
$arch = $section->{ARCH} if ($section->{ARCH});
|
||||
print "\nWhat is the name of the client(s) for $arch [$slist]: ";
|
||||
my $ans = <STDIN>; chomp $ans;
|
||||
if ($ans) {
|
||||
$ans =~ s/\s//g; # strip any whitespace
|
||||
fileReplaceText ($params{WORKLOAD}, "<CLIENT", $slist, $ans);
|
||||
}
|
||||
}
|
||||
while (1) {
|
||||
print "\nWhat additional client(s) [none]: ";
|
||||
my $ans = <STDIN>; chomp $ans;
|
||||
last unless ($ans); # done
|
||||
last if ($ans =~ /^none$/i);
|
||||
$ans =~ s/\s//g; # strip any whitespace
|
||||
my $block = "\n<CLIENT HOSTS=$ans>\n";
|
||||
|
||||
print "What OS type [default]: ";
|
||||
my $ans = <STDIN>; chomp $ans;
|
||||
$block .= " Arch\t$ans\n" if ($ans && !($ans =~ /^default$/i));
|
||||
|
||||
$block .= "</CLIENT>\n";
|
||||
fileInsertAfter ($params{WORKLOAD}, "^</CLIENT>", $block);
|
||||
}
|
||||
}
|
||||
|
||||
# Create a user ldif file
|
||||
sub configUserLdif {
|
||||
my $name = "conf/$defaultSection->{SERVER}.ldif";
|
||||
print "\nWhat file to you want to create [$name]? ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
$name = $ans if ($ans);
|
||||
|
||||
my $mode = "users";
|
||||
print "\nDo you want to create a broadcast account [y]? ";
|
||||
$ans = <STDIN>;
|
||||
$mode .= " broadcast" unless ($ans =~ /^n/i);
|
||||
|
||||
my $basedn = $defaultSection->{SERVER}; # pick a default
|
||||
$basedn =~ s/^.*?\.//; # strip off before first dot
|
||||
$basedn = "o=$basedn";
|
||||
|
||||
print "\nWhat is LDAP base DN [$basedn]? ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
$basedn = $ans if ($ans);
|
||||
|
||||
my $args = $params{MAKEUSERSARGS};
|
||||
|
||||
print "\n Common additional makeusers arguments:\n";
|
||||
print "\t-s storeName -x storeCount \tMultiple store partitions\n";
|
||||
print "\t[-3|-4] \tConfigure for NSMS 3.x or 4.x\n";
|
||||
print "Any extra arguments to makeusers [$args]? ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
$args = $ans if ($ans);
|
||||
|
||||
my $perlbin = "/usr/bin/perl";
|
||||
|
||||
$params{DEBUG} &&
|
||||
print "$perlbin -Ibin -- bin/makeusers.pl $mode -w $params{WORKLOAD} -b '$basedn' -o $name $args\n";
|
||||
|
||||
print "\nGenerating $name (this can take a while)\n";
|
||||
system "$perlbin -Ibin -- bin/makeusers.pl $mode -w $params{WORKLOAD} -b '$basedn' -o $name $args"
|
||||
|| warn "$@";
|
||||
print "LDIF generation complete. See $name\n";
|
||||
print "\tSee the manual or INSTALL to create users using the LDIF file.\n";
|
||||
}
|
||||
|
||||
# This uses a match pattern plus text to text replacements.
|
||||
# Could make all changes and then write out new workload
|
||||
# You would have to be carefull about sections with multi-line support.
|
||||
sub configWorkload {
|
||||
my $ans;
|
||||
|
||||
print "\nWhat is the name of the mail host [$defaultSection->{SERVER}]: ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
if ($ans) {
|
||||
fileReplaceText ($params{WORKLOAD},
|
||||
"(SERVER|SMTPMAILFROM|ADDRESSFORMAT)",
|
||||
$defaultSection->{SERVER}, $ans);
|
||||
$defaultSection->{SERVER} = $ans; # needed for ldif generation
|
||||
}
|
||||
print "\nWhat is the user name pattern [$defaultSection->{LOGINFORMAT}]: ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
if ($ans) {
|
||||
fileReplaceText ($params{WORKLOAD},
|
||||
"(LOGINFORMAT|ADDRESSFORMAT)",
|
||||
$defaultSection->{LOGINFORMAT}, $ans);
|
||||
$ans =~ s/%ld/0/; # create smtpMailFrom user
|
||||
my $olduser = $defaultSection->{SMTPMAILFROM};
|
||||
$olduser =~ s/@.*$//; # strip off after @
|
||||
fileReplaceText ($params{WORKLOAD},
|
||||
"SMTPMAILFROM",
|
||||
$olduser, $ans);
|
||||
}
|
||||
|
||||
print "\nWhat is the password pattern [$defaultSection->{PASSWDFORMAT}]: ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
fileReplaceText ($params{WORKLOAD}, "PASSWDFORMAT",
|
||||
$defaultSection->{PASSWDFORMAT}, $ans);
|
||||
|
||||
$defaultSection->{NUMLOGINS} = 100 unless ($defaultSection->{NUMLOGINS});
|
||||
print "\nHow many users [$defaultSection->{NUMLOGINS}]: ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
fileReplaceText ($params{WORKLOAD}, "(NUMADDRESSES|NUMLOGINS)",
|
||||
$defaultSection->{NUMLOGINS}, $ans);
|
||||
|
||||
$defaultSection->{FIRSTLOGIN} = 0 unless ($defaultSection->{FIRSTLOGIN});
|
||||
print "\nWhat is the first user number [$defaultSection->{FIRSTLOGIN}]: ";
|
||||
$ans = <STDIN>; chomp $ans;
|
||||
fileReplaceText ($params{WORKLOAD}, "(FIRSTADDRESS|FIRSTLOGIN)",
|
||||
$defaultSection->{FIRSTLOGIN}, $ans);
|
||||
|
||||
unless ($params{NT}) {
|
||||
configClients ();
|
||||
}
|
||||
|
||||
print "\nDo you want to view the edited $params{WORKLOAD} [y]? ";
|
||||
$ans = <STDIN>;
|
||||
unless ($ans =~ /^n/i) {
|
||||
print "Here is the edited $params{WORKLOAD}:\n\n";
|
||||
fileShow ($params{WORKLOAD});
|
||||
print "\n";
|
||||
}
|
||||
|
||||
print "\nDo you want to generate a user LDIF file [y]? ";
|
||||
$ans = <STDIN>;
|
||||
unless ($ans =~ /^n/i) {
|
||||
configUserLdif ();
|
||||
}
|
||||
}
|
||||
|
||||
# See if license file has been displayed
|
||||
if (($mode ne "cleanup") && (! -f ".license" )) {
|
||||
fileShow ("LICENSE");
|
||||
print "\nDo you agree to the terms of the license? (yes/no) ";
|
||||
my $ans = <STDIN>;
|
||||
print "\n";
|
||||
unless ($ans =~ /^yes$/i) {
|
||||
print "License not agreed to.\n";
|
||||
exit 0;
|
||||
}
|
||||
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
|
||||
open (LIC, ">.license");
|
||||
printf LIC "%04d$mon$mday$hour$min\n", $year+1900;
|
||||
close (LIC);
|
||||
}
|
||||
|
||||
if ($mode eq "config") { # re-run config
|
||||
configWorkload ();
|
||||
|
||||
print "\nMake any additional changes to $params{WORKLOAD} and then re-run 'setup'\n";
|
||||
exit 0;
|
||||
} elsif ($mode ne "cleanup") { # check if configured
|
||||
my $unconf = 0; # see if default values are in use
|
||||
foreach $section (@workload) {
|
||||
($section->{SERVER})
|
||||
&& ($section->{SERVER} =~ /example\.com$/)
|
||||
&& $unconf++;
|
||||
($section->{SMTPMAILFROM})
|
||||
&& ($section->{SMTPMAILFROM} =~ /example\.com$/)
|
||||
&& $unconf++;
|
||||
($section->{ADDRESSFORMAT})
|
||||
&& ($section->{ADDRESSFORMAT} =~ /example\.com$/)
|
||||
&& $unconf++;
|
||||
last if ($unconf > 0);
|
||||
}
|
||||
if ($unconf > 0) {
|
||||
print "Server has not been configured (example.com is an invalid address).\n";
|
||||
print "Do you want to setup a simple configuration now [y]?";
|
||||
my $ans = <STDIN>;
|
||||
if ($ans =~ /^n/i) {
|
||||
print "Re-run setup when you have edited the configuration.\n";
|
||||
exit 0;
|
||||
}
|
||||
configWorkload ();
|
||||
|
||||
print "\nMake any additional changes to $params{WORKLOAD} and then re-run 'setup'\n";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($mode eq "timesync") {
|
||||
if ($params{NT}) {
|
||||
print "Timesync has no effect on NT\n";
|
||||
exit 0;
|
||||
}
|
||||
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
|
||||
$mon += 1; # adjust from 0 based to std
|
||||
$systime = sprintf ("%02d%02d%02d%02d%04d.%02d",
|
||||
$mon, $mday, $hour, $min, 1900+$year, $sec);
|
||||
} elsif ($mode eq "checktime") {
|
||||
if ($params{NT}) { # if running on NT, then only single client
|
||||
print "Checktime not needed on NT\n";
|
||||
exit 0;
|
||||
}
|
||||
mkdir ("$resultbase", 0775);
|
||||
mkdir ("$tmpbase", 0775);
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
open MAKEIT, ">$tmpbase/$cli.tim";
|
||||
close MAKEIT;
|
||||
}
|
||||
}
|
||||
} elsif (($mode eq "setup") || ($mode eq "cleanup")) {
|
||||
@msgs = <data/*.msg>;
|
||||
foreach (@files = @msgs) { s/data\/// }
|
||||
print "Found these message files:\n@files\n\n";
|
||||
if ($params{NT}) { # handle NT localhost here
|
||||
exit 0 if ($mode =~ /cleanup$/);
|
||||
my $clipath = "bin/WINNT4.0/bin/mailclient.exe";
|
||||
print "Copying $clipath and message files to $cli\n";
|
||||
system "copy $clipath $params{TEMPDIR}";
|
||||
foreach $f (@files) {
|
||||
system "copy $f $params{TEMPDIR}";
|
||||
}
|
||||
exit 0; # without perl:fork, no more to do
|
||||
}
|
||||
}
|
||||
|
||||
# iterate over every client in the testbed, complete the cmd and rsh
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
|
||||
my $rcp = ($section->{RCP}) ? $section->{RCP} : $params{RCP};
|
||||
my $tempdir;
|
||||
if ($section->{TEMPDIR}) {
|
||||
$tempdir = $section->{TEMPDIR};
|
||||
} elsif ($params{TEMPDIR}) {
|
||||
$tempdir = $params{TEMPDIR};
|
||||
}
|
||||
# most time critical first
|
||||
if ($mode eq "timesync") {
|
||||
next if ($cli =~ /^localhost$/i); # dont reset our own time
|
||||
# run all these in parallel to minimize skew
|
||||
next if ($section->{ARCH} eq "NT4.0");
|
||||
forkproc ($rsh, $cli, "date $systime");
|
||||
}
|
||||
|
||||
elsif ($mode eq "checktime") {
|
||||
# run all these in parallel to minimize skew
|
||||
forkproc ($rsh, $cli, ($section->{ARCH} eq "NT4.0")
|
||||
? "time" : "date",
|
||||
"/dev/null", "$tmpbase/$cli.tim");
|
||||
}
|
||||
|
||||
elsif ($mode eq "setup") {
|
||||
my ($clibin) = split /\s/, (($section->{COMMAND})
|
||||
? $section->{COMMAND}
|
||||
: $params{CLIENTCOMMAND});
|
||||
my $clipath = "bin/$clibin";
|
||||
if ($section->{ARCH}) {
|
||||
if (-x "bin/$section->{ARCH}/bin/$clibin") {
|
||||
$clipath="bin/$section->{ARCH}/bin/$clibin";
|
||||
} else {
|
||||
print "Requested OS $section->{ARCH} $cli not found. Using default.\n";
|
||||
}
|
||||
}
|
||||
my $rdir = ($tempdir) ? "$tempdir/" : ".";
|
||||
# chmod so that the remote files can be easily cleaned up
|
||||
my $rcmd = "chmod g+w @files $clibin; uname -a";
|
||||
$rcmd = "cd $tempdir; " . $rcmd if ($tempdir);
|
||||
$rdir =~ s!/!\\!g if ($section->{ARCH} eq "NT4.0");
|
||||
if ($cli =~ /^localhost$/i) {
|
||||
die "TEMPDIR must be set for 'localhost'\n"
|
||||
unless ($tempdir);
|
||||
die "Invalid local NT copy. Should never get here.\n"
|
||||
if ($section->{ARCH} eq "NT4.0"); # should never happen
|
||||
print "Copying $clipath and message files to $rdir\n";
|
||||
system ("$cpcmd @msgs $clipath $rdir");
|
||||
system ($rcmd);
|
||||
} else {
|
||||
print "$rcp $clipath @msgs $cli:$rdir\n" if ($params{DEBUG});
|
||||
print "Copying $clipath and message files to $cli:$rdir\n";
|
||||
system (split (/\s+/, $rcp), $clipath, @msgs, "$cli:$rdir");
|
||||
next if ($section->{ARCH} eq "NT4.0"); # chmod not valid
|
||||
print "rcmd='$rcmd'\n" if ($params{DEBUG});
|
||||
system (split (/\s+/, $rsh), $cli, $rcmd);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
elsif ($mode eq "cleanup") {
|
||||
if ($params{DEBUG}) { # get debug files
|
||||
print "Cleaning up debug files on $cli\n";
|
||||
my $rcmd = ($section->{ARCH} eq "NT4.0") ? "DEL" : "$rmcmd";
|
||||
$rmcmd .= " mstone-debug.[0-9]*";
|
||||
$rcmd = "cd $tempdir; " . $rcmd if ($tempdir);
|
||||
$rcmd =~ s/;/&&/g if ($section->{ARCH} eq "NT4.0");
|
||||
if ($cli =~ /^localhost$/i) {
|
||||
die "TEMPDIR must be set for 'localhost'\n"
|
||||
unless ($tempdir);
|
||||
system ($rcmd);
|
||||
} else {
|
||||
system (split (/\s+/, $rsh), $cli, $rcmd);
|
||||
}
|
||||
} else {
|
||||
print "Cleaning $cli\n";
|
||||
my $rcmd = ($section->{ARCH} eq "NT4.0") ? "DEL" : "$rmcmd";
|
||||
$rcmd .= " $clibin @files";
|
||||
$rcmd = "cd $tempdir; " . $rcmd if ($tempdir);
|
||||
$rcmd =~ s/;/&&/g if ($section->{ARCH} eq "NT4.0");
|
||||
if ($cli =~ /^localhost$/i) {
|
||||
die "TEMPDIR must be set for 'localhost'\n"
|
||||
unless ($tempdir);
|
||||
system ($rcmd);
|
||||
} else {
|
||||
system (split (/\s+/, $rsh), $cli, $rcmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
die "Couldn't recognize mode $mode!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# wait for children to finish
|
||||
if (($mode eq "timesync") || ($mode eq "checktime")) {
|
||||
$pid = wait();
|
||||
while ($pid != -1) {
|
||||
$pid = wait();
|
||||
}
|
||||
}
|
||||
|
||||
# Print the results of the time checks
|
||||
if ($mode eq "checktime") {
|
||||
print "Time from each client:\n";
|
||||
foreach $section (@workload) {
|
||||
next unless ($section->{sectionTitle} =~ /CLIENT/o);
|
||||
my $slist = $section->{sectionParams};
|
||||
$slist =~ s/HOSTS=\s*//; # strip off initial bit
|
||||
foreach $cli (split /[\s,]/, $slist) {
|
||||
open TIMEFILE, "$tmpbase/$cli.tim"
|
||||
|| warn "Counldn't open $tmpbase/$cli.tim\n";
|
||||
printf "%32s: ", $cli;
|
||||
while (<TIMEFILE>) { print; last;} # single line (2 on NT)
|
||||
close(TIMEFILE);
|
||||
unlink "$tmpbase/$cli.tim";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#!/bin/ksh
|
||||
# fire off the series of Mailstone IMAP tests
|
||||
|
||||
# To test series setup, do: go_imap -n
|
||||
|
||||
|
||||
# Look for testname$test_form, first. Override with: go_series -f <string>.
|
||||
export test_form="_mail02"
|
||||
|
||||
export test_host="mail02"
|
||||
|
||||
# string appended to every description. Override with: go_series -d <string>.
|
||||
export desc_conf="12 CPUs"
|
||||
|
||||
# Extra arguments common to all tests. Any other args go here.
|
||||
# Note that arguments with embedded spaces wont work here.
|
||||
# Instead use: go_series -- <args...>
|
||||
export extra_args=""
|
||||
|
||||
# error limit to abort sequence
|
||||
export error_limit=500
|
||||
|
||||
# time to allow the server to calm down after each run (seconds)
|
||||
export sleep_time=120
|
||||
|
||||
# who to mail results to
|
||||
#export mail_list="me@example.com,you@example.com"
|
||||
export mail_list=""
|
||||
|
||||
# Get all the helper functions
|
||||
. test_utils.ksh
|
||||
|
||||
### This is where the series of tests is defined
|
||||
|
||||
# clean and re-start server
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would run:" "$@"
|
||||
return 0
|
||||
else
|
||||
# BUG: rsh never returns.
|
||||
# individual commands in clean work fine, but fail as a whole
|
||||
rsh -n $test_host /bin/ksh /iplanet/bin/clean$test_form &
|
||||
sleep 300 && kill -9 $!
|
||||
wait
|
||||
fi
|
||||
|
||||
# check our setup
|
||||
run timesync
|
||||
|
||||
###echo "DEBUG exit" && exit 0
|
||||
|
||||
run_test popdel 'Create mailboxes (random order)' -t 60m maxblocks=100000 "$@"
|
||||
run_test allpop 'Create mailboxes (exhaustive)' "$@"
|
||||
|
||||
run_test imaplogin 'IMAP login rate' "$@"
|
||||
|
||||
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
|
||||
sleep 200 # let queue drain (2000/(10 msg/sec))
|
||||
run_test imapread10k 'IMAP Message downloads 5k from 10k users' "$@"
|
||||
|
||||
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
|
||||
sleep 200 # let queue drain (2000/(10 msg/sec))
|
||||
run_test imapread 'IMAP Message downloads 5k' "$@"
|
||||
|
||||
run_test imapsmtp-throttle 'Combined IMAP-SMTP load (1 of 3)' "$@"
|
||||
run_test imapsmtp-throttle 'Combined IMAP-SMTP load (2 of 3)' "$@"
|
||||
run_test imapsmtp-throttle 'Combined IMAP-SMTP load (3 of 3)' "$@"
|
||||
|
||||
# Some messages will be left from previous test
|
||||
run_test imapmaxusers 'IMAP 30K simultaneous users' "$@"
|
||||
|
||||
# e-mail the whole batch
|
||||
[[ -n "$mail_list" ]] && \
|
||||
mail_series "DotCom IMAP: `date`" "$mail_list"
|
|
@ -1,84 +0,0 @@
|
|||
#!/bin/ksh
|
||||
# fire off the series of Mailstone tests
|
||||
|
||||
# To test series, do: go_series -n
|
||||
|
||||
|
||||
# Look for testname$test_form, first. Override with: go_series -f <string>.
|
||||
export test_form="_mail02"
|
||||
|
||||
export test_host="mail02"
|
||||
|
||||
# string appended to every description. Override with: go_series -d <string>.
|
||||
export desc_conf="12 CPUs"
|
||||
|
||||
# Extra arguments common to all tests. Any other args go here.
|
||||
# Note that arguments with embedded spaces wont work here.
|
||||
# Instead use: go_series -- <args...>
|
||||
export extra_args=""
|
||||
|
||||
# error limit to abort sequence
|
||||
export error_limit=500
|
||||
|
||||
# time to allow the server to calm down after each run (seconds)
|
||||
export sleep_time=120
|
||||
|
||||
# who to mail results to
|
||||
#export mail_list="me@example.com,you@example.com"
|
||||
export mail_list=""
|
||||
|
||||
# Get all the helper functions
|
||||
. test_utils.ksh
|
||||
|
||||
### This is where the series of tests is defined
|
||||
|
||||
# clean and re-start server
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would run:" "$@"
|
||||
return 0
|
||||
else
|
||||
# BUG: this never returns. rsh never returns
|
||||
# individual commands in clean work fine, but fail as a whole
|
||||
rsh -n $test_host /bin/ksh /iplanet/bin/clean$test_form &
|
||||
sleep 300 && kill -9 $!
|
||||
wait
|
||||
fi
|
||||
|
||||
# check our setup
|
||||
run timesync
|
||||
|
||||
###echo "DEBUG exit" && exit 0
|
||||
|
||||
run_test popdel 'Create mailboxes (random order)' -t 60m maxblocks=100000 "$@"
|
||||
run_test allpop 'Create mailboxes (exhaustive)' "$@"
|
||||
|
||||
run_test popdel 'Empty checks: never used (1 of 3)' "$@"
|
||||
run_test popdel 'Empty checks: never used (2 of 3)' "$@"
|
||||
run_test popdel 'Empty checks: never used (3 of 3)' "$@"
|
||||
|
||||
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
|
||||
sleep 200 # let queue drain (2000/(10 msg/sec))
|
||||
|
||||
run_test popsave10k 'Message downloads 5k from 10k users (1 of 3)' "$@"
|
||||
run_test popsave10k 'Message downloads 5k from 10k users (2 of 3)' "$@"
|
||||
run_test popsave10k 'Message downloads 5k from 10k users (3 of 3)' "$@"
|
||||
|
||||
run_test popsave 'Message downloads 5k (1 of 3)' "$@"
|
||||
run_test popsave 'Message downloads 5k (2 of 3)' "$@"
|
||||
run_test popsave 'Message downloads 5k (3 of 3)' "$@"
|
||||
|
||||
run_test popsmtp-throttle 'Combined load (1 of 3)' "$@"
|
||||
run_test popsmtp-throttle 'Combined load (2 of 3)' "$@"
|
||||
run_test popsmtp-throttle 'Combined load (3 of 3)' "$@"
|
||||
|
||||
run_test smtp100k 'SMTP delivery rate' "$@"
|
||||
|
||||
run_test popclean 'Message downloads/delete 5k ' "$@"
|
||||
|
||||
run_test popdel 'Empty checks (1 of 3)' "$@"
|
||||
run_test popdel 'Empty checks (2 of 3)' "$@"
|
||||
run_test popdel 'Empty checks (3 of 3)' "$@"
|
||||
|
||||
# e-mail the whole batch
|
||||
[[ -n "$mail_list" ]] && \
|
||||
mail_series "DotCom POP: `date`" "$mail_list"
|
|
@ -1,281 +0,0 @@
|
|||
# MailStone workload configuration file
|
||||
#
|
||||
# Include other workload files like this:
|
||||
# <include conf/morework.wld>
|
||||
#
|
||||
# If you want a workload included ONLY ONCE in the test, use this
|
||||
# <includeOnce conf/morework.wld>
|
||||
#
|
||||
# See Also:
|
||||
# smtp.wld - typical SMTP delivery test
|
||||
# pop.wld - typical POP3 check/download test
|
||||
# imap.wld - typical IMAP4 check/download test
|
||||
|
||||
|
||||
######################################################################
|
||||
# These sections discribe how the test is run:
|
||||
# CONFIG, CLIENT, MONITOR, PRETEST, POSTTEST
|
||||
|
||||
# The <CONFIG> section defines test setup and report parameters
|
||||
# Multiple <CONFIG> sections will be merged into a one.
|
||||
# The equivalent command line switch is shown in parenthesis.
|
||||
<CONFIG>
|
||||
title POP reads # title for report and index (-b)
|
||||
comments Netscape MSG4.1 # additional info at top of report (-n)
|
||||
|
||||
time 3m # test time (-t)
|
||||
rampTime 20s # portion of test to start things (-r)
|
||||
clientCount 12 # number of client connections (-l)
|
||||
|
||||
maxErrors 10000 # set an error abort limit
|
||||
maxBlocks 50000 # stop after this many blocks
|
||||
|
||||
#sysConfig conf/mailhost.txt # Pull in config file (-s)
|
||||
sysConfig \ # Inline config text
|
||||
<PRE>\
|
||||
<B> mailhost.example.com </B>\
|
||||
Netscape Messaging Server 4.11\
|
||||
Linux 2.2.5\
|
||||
4x400Mhz Xeon (1Mb)\
|
||||
2Gb RAM\
|
||||
</PRE>
|
||||
|
||||
useGroups 1 # use group names instead of host names
|
||||
|
||||
telemetry 1 # log telemetry (for debugging)
|
||||
|
||||
# These usually dont need to be set. These are the defaults
|
||||
GnuPlot gnuplot/gnuplot
|
||||
RSH ssh
|
||||
# RSH /usr/bin/remsh # HP-UX uses this path
|
||||
RCP scp
|
||||
# RCP /usr/bin/rcp
|
||||
tempDir /var/tmp # client machine directory
|
||||
chartWidth 640
|
||||
chartHeight 480
|
||||
clientCommand mailclient # CLIENT command to run
|
||||
monitorCommand vmstat %f # MONITOR command to run
|
||||
makeUsersArgs -4 # args to makeusers
|
||||
imageType png # gnuplot image type: png, gif, ...
|
||||
</CONFIG>
|
||||
|
||||
# Each <Client> section defines one or more client machines
|
||||
# Every machine in the section will run the same number of connections
|
||||
# Note that there cannot be whitespace between the client hostnames
|
||||
<CLIENT HOSTS=client1,client2>
|
||||
arch Linux2.2_x86
|
||||
maxClients 200
|
||||
maxThreads 50
|
||||
|
||||
# the group is only used if "useGroups" is set
|
||||
group A
|
||||
|
||||
command mailclient -m 100 # override the command to run
|
||||
</CLIENT>
|
||||
|
||||
# Set a specific number of processes and threads
|
||||
<CLIENT HOSTS=client3,client4>
|
||||
arch SunOS5.6
|
||||
processes 2
|
||||
threads 10
|
||||
|
||||
# the group is only used if "useGroups" is set
|
||||
group B
|
||||
</CLIENT>
|
||||
|
||||
# Here is how to configure a WinNT client from a Unix mail master
|
||||
# The NT rshd must interoperate with Unix rsh; allow redirection of
|
||||
# stdin, stdout, and stderr; and must support binary file copies.
|
||||
# Denicomp's wrshdnt has been used sucessfully. www.denicomp.com
|
||||
<CLIENT HOSTS=winnt01>
|
||||
Arch WINNT4.0
|
||||
command mailclient.exe
|
||||
tempDir c:\temp
|
||||
</CLIENT>
|
||||
|
||||
# The PreTest sections will run before the test starts
|
||||
<PRETEST HOSTS=mailhost.example.com>
|
||||
# RSH rsh -l mailuser
|
||||
command cd /usr/netscape/msg-mailhost; ./getconf
|
||||
</PRETEST>
|
||||
|
||||
# Each <Monitor> section defines remote monitoring commands
|
||||
# for one or more machines.
|
||||
# Commands containing '%c' run to completion.
|
||||
# Otherwise the command will be shutdown down
|
||||
<MONITOR HOSTS=mailhost.example.com>
|
||||
command vmstat,%f,%c
|
||||
</MONITOR>
|
||||
|
||||
# The PostTest sections will run after the test completes
|
||||
<POSTTEST HOSTS=mailhost.example.com>
|
||||
command df
|
||||
</POSTTEST>
|
||||
|
||||
|
||||
######################################################################
|
||||
# available protcols: SMTP, POP3, IMAP4
|
||||
# (command names are not case sensitive)
|
||||
#
|
||||
# Time formats use suffixes of 's', 'm', 'h', 'd'
|
||||
# for seconds, minutes, hours, days
|
||||
# In account formats, "%ld" is replaced by user number
|
||||
|
||||
# These parameters apply to the protocol sections
|
||||
# Command parameter applicable command Example
|
||||
#-------------------------------------------------------------------
|
||||
# server <ALL> mail.example.com
|
||||
# portNum <ALL> 25
|
||||
# (if no value is given, the default port for that service is used)
|
||||
#
|
||||
# weight <ALL> 20
|
||||
#
|
||||
# loginFormat <ALL> test%ld
|
||||
# %ld=address %ld=domain
|
||||
# firstLogin <ALL> 0
|
||||
# numLogins <ALL> 2000
|
||||
# sequentialLogins <ALL> 1
|
||||
# passwdFormat <ALL> netscape
|
||||
#
|
||||
# addressFormat <ALL> test%ld@mail.example%ld.com
|
||||
# %ld=address %ld=domain
|
||||
# firstAddress <ALL> 0
|
||||
# numAddresses <ALL> 2000
|
||||
# sequentialAddresses <ALL> 1
|
||||
#
|
||||
# numDomains <ALL> 3
|
||||
# firstDomain <ALL> 0
|
||||
# sequentialDomains <ALL> 1
|
||||
#
|
||||
# idleTime <ALL> 5m
|
||||
# numLoops <ALL> 200
|
||||
# loopDelay <ALL> 1m
|
||||
# blockTime <ALL> 5m
|
||||
#
|
||||
# numRecips SMTP 3
|
||||
# smtpMailFrom SMTP mailstone@mail.example.com
|
||||
# file SMTP en-3k.msg
|
||||
# useEHLO SMTP 1 (default is HELO)
|
||||
# useAUTHLOGIN SMTP 1 (no AUTHLOGIN by default)
|
||||
#
|
||||
# leaveMailOnServer POP3,IMAP4 1
|
||||
# leaveMailUnSeen IMAP4 1
|
||||
|
||||
# The <Default> section sets command block defaults
|
||||
# Multiple <Default> sections will be merged into one
|
||||
<DEFAULT>
|
||||
server mailhost.example.com
|
||||
smtpMailFrom mailhost0@mailhost.example.com
|
||||
addressFormat mailhost%ld@mailhost.example.com
|
||||
loginFormat mailhost%ld
|
||||
passwdFormat netscape
|
||||
numLogins 1000
|
||||
numAddresses 1000
|
||||
</DEFAULT>
|
||||
|
||||
# Note: empty host list means all hosts
|
||||
<SMTP>
|
||||
file en-1k.msg
|
||||
weight 10
|
||||
numAddresses 200
|
||||
</SMTP>
|
||||
|
||||
<include conf/smtp17.wld>
|
||||
|
||||
# Note: the host name must be the same as specified in the CLIENT section
|
||||
<POP3 HOSTS=client1,client2>
|
||||
weight 10
|
||||
#leaveMailOnServer 1
|
||||
</POP3>
|
||||
|
||||
<IMAP4 HOSTS=client3>
|
||||
idleTime 300
|
||||
#weight 15
|
||||
</IMAP4>
|
||||
|
||||
|
||||
######################################################################
|
||||
# These sections are used to generate the right graphs for the test
|
||||
# This is the built in defaults
|
||||
<GRAPH name=connects>
|
||||
title Number of connections attempted
|
||||
label Connections/sec
|
||||
variables conn
|
||||
field Try
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=connections>
|
||||
title Total connections
|
||||
label Connections
|
||||
variables connections
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=connErrors>
|
||||
title Number of connection errors
|
||||
label Errors/sec
|
||||
variables conn, banner, login, logout
|
||||
field Error
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=msgErrors>
|
||||
title Number of command/message errors
|
||||
label Errors/sec
|
||||
variables cmd, submit, retrieve
|
||||
field Error
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=retrieves>
|
||||
Title Number of messages read
|
||||
label Messages/sec
|
||||
variables retrieve
|
||||
field Try
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=submits>
|
||||
title Number of messages written
|
||||
label Messages/sec
|
||||
variables submit
|
||||
field Try
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=commands>
|
||||
title Number of commands sent
|
||||
label Commands/sec
|
||||
variables cmd
|
||||
field Try
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=readBytes>
|
||||
title Bytes read
|
||||
label Bytes/sec
|
||||
variables login, banner, cmd, retrieve, submit, logout
|
||||
field BytesR
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=writeBytes>
|
||||
title Bytes written
|
||||
label Bytes/sec
|
||||
variables login, banner, cmd, retrieve, submit, logout
|
||||
field BytesW
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=msgTime>
|
||||
title Message transfer time
|
||||
label Seconds per message
|
||||
variables cmd, submit, retrieve
|
||||
field Time
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=setupTime>
|
||||
Title Connection setup time
|
||||
label Seconds per connection
|
||||
variables conn, banner, login
|
||||
field Time
|
||||
</GRAPH>
|
||||
|
||||
<GRAPH name=blocks>
|
||||
title Number of mailstone blocks executed
|
||||
label Blocks/sec
|
||||
variables blocks
|
||||
# this is a scalar. No "field" needed/allowed
|
||||
</GRAPH>
|
|
@ -1,74 +0,0 @@
|
|||
#!/bin/ksh
|
||||
# fire off the series of Mailstone WEBMAIL tests
|
||||
|
||||
# To test series setup, do: go_webmail -n
|
||||
|
||||
|
||||
# Look for testname$test_form, first. Override with: go_series -f <string>.
|
||||
export test_form="_mail02"
|
||||
|
||||
export test_host="mail02"
|
||||
|
||||
# string appended to every description. Override with: go_series -d <string>.
|
||||
export desc_conf="12 CPUs"
|
||||
|
||||
# Extra arguments common to all tests. Any other args go here.
|
||||
# Note that arguments with embedded spaces wont work here.
|
||||
# Instead use: go_series -- <args...>
|
||||
export extra_args=""
|
||||
|
||||
# error limit to abort sequence
|
||||
export error_limit=500
|
||||
|
||||
# time to allow the server to calm down after each run (seconds)
|
||||
export sleep_time=120
|
||||
|
||||
# who to mail results to
|
||||
#export mail_list="me@example.com,you@example.com"
|
||||
export mail_list=""
|
||||
|
||||
# Get all the helper functions
|
||||
. test_utils.ksh
|
||||
|
||||
### This is where the series of tests is defined
|
||||
|
||||
# clean and re-start server
|
||||
if [[ $only_show_it -gt 0 ]] ; then
|
||||
echo "Would run:" "$@"
|
||||
return 0
|
||||
else
|
||||
# BUG: rsh never returns.
|
||||
# individual commands in clean work fine, but fail as a whole
|
||||
rsh -n $test_host /bin/ksh /iplanet/bin/clean$test_form &
|
||||
sleep 300 && kill -9 $!
|
||||
wait
|
||||
fi
|
||||
|
||||
# check our setup
|
||||
run timesync
|
||||
|
||||
###echo "DEBUG exit" && exit 0
|
||||
|
||||
run_test popdel 'Create mailboxes (random order)' -t 60m maxblocks=100000 "$@"
|
||||
run_test allpop 'Create mailboxes (exhaustive)' "$@"
|
||||
|
||||
run_test webmaillogin 'WebMail login rate' "$@"
|
||||
|
||||
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
|
||||
sleep 200 # let queue drain (2000/(10 msg/sec))
|
||||
run_test webmailread10k 'WebMail Message downloads 5k from 10k users' "$@"
|
||||
|
||||
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
|
||||
sleep 200 # let queue drain (2000/(10 msg/sec))
|
||||
run_test webmailread 'WebMail Message downloads 5k' "$@"
|
||||
|
||||
run_test webmailsmtp-throttle 'Combined WebMail-SMTP load (1 of 3)' "$@"
|
||||
run_test webmailsmtp-throttle 'Combined WebMail-SMTP load (2 of 3)' "$@"
|
||||
run_test webmailsmtp-throttle 'Combined WebMail-SMTP load (3 of 3)' "$@"
|
||||
|
||||
# Some messages will be left from previous test
|
||||
run_test webmailmaxusers 'WebMail 30K simultaneous users' "$@"
|
||||
|
||||
# e-mail the whole batch
|
||||
[[ -n "$mail_list" ]] && \
|
||||
mail_series "DotCom WebMail: `date`" "$mail_list"
|
|
@ -1,72 +0,0 @@
|
|||
#!/bin/sh
|
||||
# package an OS into a multi-OS tree
|
||||
# usage ospkg.sh targetOS os...
|
||||
|
||||
target=$1; shift
|
||||
pkgdir=./build/package/$target/mstone
|
||||
|
||||
errors=0
|
||||
|
||||
for obj
|
||||
do
|
||||
srcdir=./build/package/$obj/mstone
|
||||
if [ ! -d $srcdir ] ; then
|
||||
echo "Error! Source directory $srcdir is missing."
|
||||
errors=1
|
||||
continue;
|
||||
fi
|
||||
arch=`echo $obj | sed -e 's/_OPT.OBJ//' | sed -e 's/_DBG.OBJ//'`
|
||||
|
||||
echo "===== adding $arch packaging to $pkgdir"
|
||||
|
||||
echo "Installing mailclient"
|
||||
[ -d $pkgdir/bin/$arch/bin ] || mkdir -p $pkgdir/bin/$arch/bin
|
||||
cp -p $srcdir/bin/mailclient $pkgdir/bin/$arch/bin/
|
||||
|
||||
if [ -d $srcdir/gd ] ; then
|
||||
echo "Installing gd"
|
||||
[ -d $pkgdir/bin/$arch/gd ] || mkdir -p $pkgdir/bin/$arch/gd
|
||||
cp -p $srcdir/gd/* $pkgdir/bin/$arch/gd/
|
||||
fi
|
||||
|
||||
if [ -d $srcdir/gnuplot ] ; then
|
||||
echo "Installing gnuplot"
|
||||
[ -d $pkgdir/bin/$arch/gnuplot ] || mkdir -p $pkgdir/bin/$arch/gnuplot
|
||||
cp -p $srcdir/gnuplot/* $pkgdir/bin/$arch/gnuplot/
|
||||
fi
|
||||
|
||||
if [ -d $srcdir/perl ] ; then
|
||||
perlver=`cd $srcdir/perl/lib; ls -d 5.* | head -1`
|
||||
perlarch=`cd $srcdir/perl/lib/$perlver; ls -d */Config.pm | cut -f1 -d/`
|
||||
echo "Installing perl $perlver for $perlarch"
|
||||
[ -d $pkgdir/perl ] || mkdir -p $pkgdir/perl
|
||||
cp -pf $srcdir/perl/Artistic $pkgdir/perl/
|
||||
|
||||
# we dont pull everything in, just the potentially useful parts
|
||||
for subdir in man/man1 \
|
||||
lib/$perlver lib/$perlver/$perlarch \
|
||||
lib/$perlver/Time lib/$perlver/Term lib/$perlver/Class \
|
||||
lib/$perlver/Sys lib/$perlver/Data lib/$perlver/Getopt \
|
||||
lib/$perlver/Test lib/$perlver/Text \
|
||||
lib/$perlver/File lib/$perlver/File/Spec \
|
||||
lib/$perlver/CGI lib/$perlver/Net \
|
||||
lib/$perlver/$perlarch/auto/DynaLoader \
|
||||
lib/$perlver/$perlarch/auto/Socket \
|
||||
lib/$perlver/$perlarch/auto/re \
|
||||
lib/$perlver/$perlarch/auto/attrs
|
||||
do
|
||||
[ -d $srcdir/perl/$subdir ] || continue;
|
||||
[ -d $pkgdir/perl/$subdir ] || mkdir -p $pkgdir/perl/$subdir
|
||||
# HACK: all the files have dots in them, directories dont
|
||||
cp -pf $srcdir/perl/$subdir/*.* $pkgdir/perl/$subdir
|
||||
done
|
||||
|
||||
# where we put multi-os perl binaries
|
||||
perlbin=$pkgdir/perl/arch/$arch
|
||||
[ -d $perlbin ] || mkdir -p $perlbin
|
||||
cp -p $srcdir/perl/bin/* $perlbin/
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
exit $errors
|
|
@ -1,514 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
* Mike Blakely
|
||||
* David Shak
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
#ifndef __BENCH_H__
|
||||
#define __BENCH_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include <io.h>
|
||||
#define NT_STACKSIZE 50*1024
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#ifdef USE_PTHREADS
|
||||
#include <sys/signal.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/poll.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h> /* for struct rlimit, RLIMIT_NOFILE */
|
||||
#ifdef HAVE_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#ifdef HAVE_WAIT_H
|
||||
#include <wait.h>
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#define USECINSEC 1000000
|
||||
#define MSECINSEC 1000
|
||||
#define MAX_ACCEPT_SECS 180 /* maximum time master will wait for listen() */
|
||||
|
||||
#define SECS_2_USECS(x) ((x) * USECINSEC)
|
||||
#define USECS_2_SECS(x) ((x) / USECINSEC)
|
||||
|
||||
#define LINE_BUFSIZE 4096
|
||||
#define MAXPROCSPERNODE 4096 /* max # of procs/node */
|
||||
|
||||
#define SMTP_PORT 25 /* standard port numbers */
|
||||
#define POP3_PORT 110
|
||||
#define IMAP4_PORT 143
|
||||
#define HTTP_PORT 80
|
||||
#define WMAP_PORT 80
|
||||
|
||||
#define CRLF "\r\n"
|
||||
|
||||
#define MAX_USERNAME_LEN 32
|
||||
#define MAX_MAILADDR_LEN 64
|
||||
#define MAX_COMMAND_LEN (2*1024)
|
||||
#define MAX_RESPONSE_LEN (2*1024)
|
||||
#define MAX_ERRORMSG_LEN 256
|
||||
#define DATESTAMP_LEN 40
|
||||
|
||||
#define MAX_IMAP_FOLDERNAME_LEN 256
|
||||
#define MAX_SEARCH_PATTERN_LEN 256
|
||||
|
||||
#define MAX_HTTP_COMMAND_LEN 1024
|
||||
|
||||
/* TODO make these dynamic. For now just use big buffers */
|
||||
#define SIZEOF_EVENTTEXT 150 /* report text from a single timer */
|
||||
#define SIZEOF_RQSTSTATSTEXT 2048 /* report text from all timers */
|
||||
#define SIZEOF_SUMMARYTEXT 8192 /* report text from all protocols */
|
||||
|
||||
/* levels for timeexpired */
|
||||
#define EXIT_SOON 1 /* do a clean shutdown ASAP */
|
||||
#define EXIT_FAST 20 /* shutdown now, dont block */
|
||||
#define EXIT_FASTEST 50 /* close sockets unconnditionally */
|
||||
|
||||
/* Debug macros */
|
||||
#define D_PRINTF if (gn_debug > 0) d_printf
|
||||
#define T_PRINTF if (gn_record_telemetry) t_printf
|
||||
|
||||
/*
|
||||
Simple keyword indexed string storage
|
||||
This kind of thing has been invented many times. Once more with gusto!
|
||||
*/
|
||||
typedef struct param_list {
|
||||
struct param_list *next;
|
||||
char * name;
|
||||
char * value;
|
||||
} param_list_t;
|
||||
|
||||
/*
|
||||
Simple keyword indexed string storage
|
||||
This kind of thing has been invented many times. Once more with gusto!
|
||||
*/
|
||||
typedef struct string_list {
|
||||
struct string_list *next;
|
||||
char * value;
|
||||
} string_list_t;
|
||||
|
||||
/* Numeric range (Shared). Previous value must be stored seperately */
|
||||
typedef struct range {
|
||||
unsigned long first; /* first valid value */
|
||||
unsigned long last; /* last valid value */
|
||||
unsigned long span; /* last-first */
|
||||
int sequential; /* 0=random, +=sequential up, -=down */
|
||||
} range_t;
|
||||
|
||||
/* basic timing structure */
|
||||
typedef struct event_timer {
|
||||
unsigned long trys;
|
||||
unsigned long errs;
|
||||
double bytesread;
|
||||
double byteswritten;
|
||||
double elapsedtime;
|
||||
double elapsedtimesq;
|
||||
double maxtime;
|
||||
double mintime;
|
||||
} event_timer_t;
|
||||
|
||||
/* command stats kept for every block and for every thread */
|
||||
typedef struct cmd_stats {
|
||||
/* This is protocol independent */
|
||||
unsigned long totalerrs;
|
||||
unsigned long totalcommands;
|
||||
event_timer_t combined; /* AKA total */
|
||||
event_timer_t idle;
|
||||
|
||||
void * data; /* protocol dependent data */
|
||||
} cmd_stats_t;
|
||||
|
||||
typedef struct stats { /* used for throttling ??? */
|
||||
struct timeval starttime;
|
||||
struct timeval endtime;
|
||||
unsigned int total_num_of_commands;
|
||||
} stats_t;
|
||||
|
||||
typedef struct resolved_addr {
|
||||
char * hostName; /* name of server */
|
||||
NETPORT portNum; /* port ot use */
|
||||
int resolved;
|
||||
struct hostent host_phe;
|
||||
struct protoent host_ppe;
|
||||
unsigned long host_addr;
|
||||
short host_type;
|
||||
} resolved_addr_t;
|
||||
|
||||
typedef struct thread_context *ptcx_t;
|
||||
typedef struct mail_command *pmail_command_t;
|
||||
typedef struct protocol *p_protocol_t;
|
||||
typedef int (*parseStartPtr_t)(pmail_command_t, char *, param_list_t *);
|
||||
typedef int (*parseEndPtr_t)(pmail_command_t, string_list_t *, param_list_t *);
|
||||
typedef void *(*commStartPtr_t)(ptcx_t , pmail_command_t , cmd_stats_t *);
|
||||
typedef int (*commLoopPtr_t)(ptcx_t , pmail_command_t , cmd_stats_t *, void *);
|
||||
typedef void (*commEndPtr_t)(ptcx_t , pmail_command_t , cmd_stats_t *, void *);
|
||||
typedef void (*statsFormatPtr_t)(p_protocol_t, const char *extra, char *buf);
|
||||
typedef void (*statsInitPtr_t)(pmail_command_t, cmd_stats_t *, int, int);
|
||||
typedef void (*statsUpdatePtr_t)(p_protocol_t, cmd_stats_t *, cmd_stats_t *);
|
||||
typedef void (*statsOutputPtr_t)(p_protocol_t, cmd_stats_t *, char *);
|
||||
|
||||
typedef struct protocol {
|
||||
const char * name; /* text name */
|
||||
parseStartPtr_t parseStart; /* section start parse routine */
|
||||
parseEndPtr_t parseEnd; /* section end parse routine */
|
||||
|
||||
commStartPtr_t cmdStart; /* command start routine */
|
||||
commLoopPtr_t cmdLoop; /* command loop routine */
|
||||
commEndPtr_t cmdEnd; /* command end routine */
|
||||
|
||||
statsFormatPtr_t statsFormat; /* output format information */
|
||||
statsInitPtr_t statsInit; /* init and zero stats structure */
|
||||
statsUpdatePtr_t statsUpdate; /* sum commands */
|
||||
statsOutputPtr_t statsOutput; /* output stats */
|
||||
|
||||
int cmdCount; /* commands using this protocol */
|
||||
cmd_stats_t stats; /* total stats for this protocol */
|
||||
} protocol_t;
|
||||
|
||||
/* This structure defines a mail command */
|
||||
typedef struct mail_command {
|
||||
/* Required fields */
|
||||
protocol_t * proto;
|
||||
int weight;
|
||||
|
||||
/* These are protocol independent (client.c) */
|
||||
int blockID; /* ID number for each block */
|
||||
int numLoops; /* typically messages per connection */
|
||||
int idleTime; /* time to idle before loops */
|
||||
int loopDelay; /* time to idle after each loop */
|
||||
int blockTime; /* time to idle after block */
|
||||
int throttle; /* to simulate ops/sec (BROKEN) */
|
||||
|
||||
void *data; /* protocol specific data */
|
||||
} mail_command_t;
|
||||
|
||||
typedef struct child_context { /* forked sub processes */
|
||||
int pid;
|
||||
SOCKET socket;
|
||||
} ccx_t, *pccx_t;
|
||||
|
||||
typedef struct thread_context {
|
||||
/* initialized by parent thread */
|
||||
THREAD_ID tid; /* thread id */
|
||||
int processnum; /* ordinal process number */
|
||||
int threadnum; /* ordinal thread number */
|
||||
int random_seed; /* seed for srandom */
|
||||
|
||||
/* local thread context, also read by parent */
|
||||
int blockCount; /* how many command blocks */
|
||||
int connectCount; /* how many connections */
|
||||
stats_t timestat; /* throttle info */
|
||||
cmd_stats_t *cmd_stats; /* stats for each command */
|
||||
|
||||
/* temporary storage (event_start, event_stop) */
|
||||
struct timeval starttime; /* a starting timestamp */
|
||||
int bytesread; /* num bytes read in per event */
|
||||
int byteswritten; /* num bytes written per event */
|
||||
|
||||
int ofd; /* connection to master */
|
||||
FILE *dfile; /* debug file */
|
||||
int logfile; /* telemetry log file */
|
||||
|
||||
SOCKET sock; /* network connection */
|
||||
char errMsg[MAX_ERRORMSG_LEN]; /* low level error string */
|
||||
} tcx_t;
|
||||
|
||||
/* About errMsg:
|
||||
This should store what was being attempted when a IO error occurs.
|
||||
From errMsg and errno (or its NT equivalent) you should be able
|
||||
to understand what went wrong.
|
||||
|
||||
No message is printed by the common functions (since some errors are
|
||||
recoverable).
|
||||
|
||||
The protocol handlers combine errMsg with neterrstr() to generate
|
||||
the message that the user sees (if not handled by the protocol).
|
||||
|
||||
Note that this is a small buffer (since it is replicated with every
|
||||
thread). Don't try to stuff the read/written data into it.
|
||||
|
||||
The routine getting the system error sets errMsg (strcpy, or sprintf).
|
||||
Calling routines append a "call trace" with additional info (strcat).
|
||||
The "call trace" starts with '<' as a seperator.
|
||||
*/
|
||||
#define debugfile (ptcx->dfile)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(x,y) (((x) >= (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
/* routines in bench.c */
|
||||
extern void event_start(ptcx_t ptcx, event_timer_t *pevent);
|
||||
extern void event_stop(ptcx_t ptcx, event_timer_t *pevent);
|
||||
extern void event_reset(event_timer_t *pevent);
|
||||
extern void event_sum(event_timer_t *psum, event_timer_t *pincr);
|
||||
extern char *event_to_text(event_timer_t *pevent, char *ebuf);
|
||||
extern void stats_init(stats_t *);
|
||||
|
||||
extern char * double_to_text(const double the_double, char *textbuf);
|
||||
#if 0
|
||||
extern cmd_stats_t *text_to_cmd_stats(ptcx_t ptcx, char *cmd_stats_as_text, cmd_stats_t *the_cmd_stats);
|
||||
extern cmd_stats_t * text_to_cmd_stats(ptcx_t ptcx, char *, cmd_stats_t *the_cmd_stats);
|
||||
extern stats_t * text_to_stats(ptcx_t ptcx, char *, stats_t *the_stats);
|
||||
extern char * stats_to_text(ptcx_t ptcx, const stats_t *, char *statstextbuf);
|
||||
#endif
|
||||
|
||||
/* shared variables */
|
||||
extern int gn_debug;
|
||||
extern int gn_record_telemetry;
|
||||
extern int gn_total_weight;
|
||||
extern int gn_client_throttle;
|
||||
extern int gn_maxerrorcnt;
|
||||
extern int gn_maxBlockCnt;
|
||||
extern int gn_numprocs;
|
||||
extern int gn_numthreads;
|
||||
extern int gn_feedback_secs;
|
||||
extern time_t gt_testtime;
|
||||
extern time_t gt_startedtime;
|
||||
extern volatile time_t gt_shutdowntime;
|
||||
extern volatile int gf_timeexpired;
|
||||
extern time_t gt_stopinterval; /* MAX (ramptime/5, 10) */
|
||||
extern time_t gt_aborttime; /* startedtime + testtime + ramptime*/
|
||||
extern int gn_number_of_commands;
|
||||
extern int gf_abortive_close;
|
||||
extern int gf_imapForceUniqueness;
|
||||
extern char gs_dateStamp[DATESTAMP_LEN];
|
||||
extern char gs_thishostname[];
|
||||
extern char *gs_parsename;
|
||||
extern pid_t gn_myPID;
|
||||
extern mail_command_t *g_loaded_comm_list; /* actually a dynamic array */
|
||||
extern protocol_t g_protocols[];
|
||||
extern const char *gs_eventToTextFormat;
|
||||
|
||||
|
||||
/* more routines in bench.c */
|
||||
extern void *mymalloc(size_t size);
|
||||
extern void *mycalloc(size_t size);
|
||||
extern void *myrealloc(void *ptr, size_t size);
|
||||
extern void myfree(void *ptr);
|
||||
extern char *mystrdup(const char *cp);
|
||||
|
||||
extern int timeval_clear(struct timeval *tv);
|
||||
extern int timeval_stamp(struct timeval *tv);
|
||||
|
||||
extern int waitReadWrite(int fd, int flags);
|
||||
extern int retryRead(ptcx_t ptcx, SOCKET sock, char *buf, int count);
|
||||
extern int retryWrite(ptcx_t ptcx, SOCKET sock, char *buf, int count);
|
||||
|
||||
extern int recvdata(ptcx_t ptcx, SOCKET sock, char *ptr, int nbytes);
|
||||
extern int senddata(ptcx_t ptcx, SOCKET sock, char *ptr, int nbytes);
|
||||
extern void rqstat_times(cmd_stats_t *rs, cmd_stats_t *rt);
|
||||
extern void rqstat_to_buffer(char *buf, char *comm, cmd_stats_t *stats);
|
||||
extern int readResponse(ptcx_t ptcx, SOCKET sock, char *buffer, int buflen);
|
||||
extern int sendCommand(ptcx_t ptcx, SOCKET sock, char *command);
|
||||
extern int doCommandResponse(ptcx_t ptcx, SOCKET sock, char *command, char *response, int resplen);
|
||||
extern int sendOutput(int fd, char *command);
|
||||
extern int retrMsg(ptcx_t ptcx, char *buffer, int maxBytes, SOCKET sock);
|
||||
extern void trimEndWhite (char *buff);
|
||||
unsigned long rangeNext (range_t *, unsigned long );
|
||||
void rangeSetFirstLast (range_t *, unsigned long , unsigned long , int );
|
||||
void rangeSetFirstCount (range_t *, unsigned long , unsigned long , int );
|
||||
void rangeSplit (range_t *whole, range_t *sub, int pnum, int tnum);
|
||||
extern void cmdStatsInit (cmd_stats_t *p);
|
||||
|
||||
/* routines in sysdep.c */
|
||||
extern void MS_usleep(unsigned int microsecs);
|
||||
extern void MS_sleep(unsigned int secs);
|
||||
|
||||
/* routines in errexit.c */
|
||||
extern void errexit(FILE *dfile, const char *, ...);
|
||||
extern int returnerr(FILE *dfile, const char *, ...);
|
||||
extern int d_printf(FILE *dfile, const char *, ...);
|
||||
extern int t_printf(int fd, const char *buffer, size_t count, const char *format, ...);
|
||||
extern char *neterrstr(void);
|
||||
|
||||
/* routines in smtp.c */
|
||||
/* TRANSITION functions */
|
||||
extern void pishStatsFormat (protocol_t *pp, const char *extra, char *buf);
|
||||
extern void pishStatsInit(pmail_command_t, cmd_stats_t *, int pN, int tN);
|
||||
extern void pishStatsUpdate(protocol_t *, cmd_stats_t *, cmd_stats_t *);
|
||||
extern void pishStatsOutput(protocol_t *, cmd_stats_t *, char *);
|
||||
|
||||
extern int SmtpParseStart (pmail_command_t , char *, param_list_t *);
|
||||
extern int SmtpParseEnd (pmail_command_t , string_list_t *, param_list_t *);
|
||||
extern void *sendSMTPStart(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
|
||||
extern int sendSMTPLoop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
extern void sendSMTPEnd(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
|
||||
/* routines in pop3.c */
|
||||
extern int Pop3ParseStart (pmail_command_t , char *, param_list_t *);
|
||||
extern int Pop3ParseEnd (pmail_command_t , string_list_t *, param_list_t *);
|
||||
extern void *doPop3Start(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
|
||||
extern int doPop3Loop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
extern void doPop3End(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
|
||||
|
||||
/* routines in imap4.c */
|
||||
extern int Imap4ParseStart (pmail_command_t , char *, param_list_t *);
|
||||
extern int Imap4ParseEnd (pmail_command_t , string_list_t *, param_list_t *);
|
||||
extern void *doImap4Start(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
|
||||
extern int doImap4Loop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
extern void doImap4End(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
|
||||
/* routines in http.c */
|
||||
extern int HttpParseStart (pmail_command_t , char *, param_list_t *);
|
||||
extern int HttpParseEnd (pmail_command_t , string_list_t *, param_list_t *);
|
||||
extern void HttpStatsFormat (protocol_t *pp, const char *extra, char *buf);
|
||||
extern void HttpStatsInit(pmail_command_t, cmd_stats_t *, int pN, int tN);
|
||||
extern void HttpStatsUpdate(protocol_t *, cmd_stats_t *, cmd_stats_t *);
|
||||
extern void HttpStatsOutput(protocol_t *, cmd_stats_t *, char *);
|
||||
extern void *doHttpStart(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
|
||||
extern int doHttpLoop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
extern void doHttpEnd(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
|
||||
/* routines in wmap.c */
|
||||
extern int WmapParseStart (pmail_command_t , char *, param_list_t *);
|
||||
extern int WmapParseEnd (pmail_command_t , string_list_t *, param_list_t *);
|
||||
extern void WmapStatsFormat (protocol_t *pp, const char *extra, char *buf);
|
||||
extern void WmapStatsInit(pmail_command_t, cmd_stats_t *, int pN, int tN);
|
||||
extern void WmapStatsUpdate(protocol_t *, cmd_stats_t *, cmd_stats_t *);
|
||||
extern void WmapStatsOutput(protocol_t *, cmd_stats_t *, char *);
|
||||
extern void *doWmapStart(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
|
||||
extern int doWmapLoop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
extern void doWmapEnd(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
|
||||
|
||||
/* routines in parse.c */
|
||||
extern char *string_tolower(char *string);
|
||||
extern char *string_unquote(char *string);
|
||||
extern int cmdParseNameValue (pmail_command_t cmd, char *name, char *tok);
|
||||
extern int time_atoi(const char *pstr);
|
||||
extern int load_commands(char *commands);
|
||||
extern param_list_t *paramListInit (void);
|
||||
/* paramListAdd returns: 1 update existing value, 0 new, -1 out of memory */
|
||||
extern int paramListAdd (param_list_t *list, const char *name, const char *value);
|
||||
/* paramListGet returns value or NULL */
|
||||
extern char *paramListGet (param_list_t *list, const char *name);
|
||||
extern param_list_t *g_default_params; /* default section params */
|
||||
extern string_list_t *stringListInit (const char *value);
|
||||
extern int stringListAdd (string_list_t *list, const char *value);
|
||||
extern void stringListFree (string_list_t *list);
|
||||
|
||||
/* routines in timefunc.c */
|
||||
extern double timevaldouble(struct timeval *);
|
||||
extern void doubletimeval(const double, struct timeval *);
|
||||
extern double compdifftime_double(struct timeval *End, struct timeval *Strt);
|
||||
|
||||
/* routines in main.c */
|
||||
extern char *safe_inet_ntoa(struct in_addr ina, char *psz);
|
||||
|
||||
extern SOCKET connectSocket(ptcx_t ptcx, resolved_addr_t *, char *protocol);
|
||||
extern int set_abortive_close(SOCKET sock);
|
||||
|
||||
extern void throttle(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *timer);
|
||||
|
||||
/* routines in client.c */
|
||||
extern void beginShutdown (void);
|
||||
extern int clientInit(ptcx_t ptcx);
|
||||
extern int clientLoop(ptcx_t ptcx);
|
||||
extern THREAD_RET clientThread(void *);
|
||||
extern void clientSummary(ptcx_t ptcxs, int ntcxs, int ii, int outfd);
|
||||
extern THREAD_RET summaryThread(void *);
|
||||
extern int clientProc(int pnum, SOCKET outfd, unsigned int timeleft, unsigned int thread_stagger_usec);
|
||||
|
||||
extern void MS_idle(ptcx_t ptcx, int idleSecs);
|
||||
extern int resolve_addrs(char *host, char *protocol, struct hostent *host_phe,
|
||||
struct protoent *proto_ppe, unsigned long *addr,
|
||||
short *type);
|
||||
#if 0
|
||||
extern void dumpevent(ptcx_t ptcx, event_timer_t *pevent);
|
||||
extern void dumptimer(ptcx_t ptcx, cmd_stats_t *rqsttimer);
|
||||
extern int clientStats(ptcx_t ptcx);
|
||||
unsigned long get_next_login(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *ptimer);
|
||||
unsigned long get_next_address(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *ptimer);
|
||||
#endif
|
||||
|
||||
#undef VERSION
|
||||
#define VERSION "4.2"
|
||||
#ifdef _DEBUG
|
||||
#define MAILCLIENT_VERSION "mailclient (" VERSION " DEBUG built " __DATE__ " " __TIME__ ")"
|
||||
#else
|
||||
#define MAILCLIENT_VERSION "mailclient (" VERSION " built " __DATE__ " " __TIME__ ")"
|
||||
#endif
|
||||
|
||||
FILE *fdopen(int fildes, const char *mode);
|
||||
#ifndef _WIN32
|
||||
extern int getopt(int, char *const *, const char *);
|
||||
#endif
|
||||
#ifndef __OSF1__
|
||||
#ifndef __LINUX__
|
||||
extern long random(void);
|
||||
#endif
|
||||
extern void srandom(unsigned);
|
||||
#endif
|
||||
|
||||
#endif /* !__BENCH_H__ */
|
|
@ -1,908 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
/*
|
||||
client.c handles thread creation
|
||||
login, loop, logout
|
||||
status report generation
|
||||
throttling (not supported yet)
|
||||
thread joining
|
||||
*/
|
||||
|
||||
#include "bench.h"
|
||||
|
||||
static int StartedThreads = 0; /* counter semaphore for children */
|
||||
static int FinishedThreads = 0; /* counter semaphore for children */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DEBUG_FILE "mstone-debug"
|
||||
#define LOG_FILE "mstone-log"
|
||||
#else
|
||||
#define DEBUG_FILE "mstone-debug"
|
||||
#define LOG_FILE "mstone-log"
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
This is a sleep that knows about test end.
|
||||
Should also do throttling.
|
||||
We dont check for signals because the only signal expected is test end
|
||||
*/
|
||||
void
|
||||
MS_idle(ptcx_t ptcx, int idleSecs)
|
||||
{
|
||||
int secsLeft = 0;
|
||||
|
||||
secsLeft = gt_shutdowntime - time(0L);
|
||||
|
||||
D_PRINTF(debugfile, "secsLeft=%d, idleSecs=%d\n", secsLeft, idleSecs);
|
||||
|
||||
if (secsLeft <= 0) { /* time is up, start exiting */
|
||||
if (gf_timeexpired < EXIT_SOON)
|
||||
gf_timeexpired = EXIT_SOON;
|
||||
return;
|
||||
}
|
||||
|
||||
if (idleSecs > secsLeft) idleSecs = secsLeft;
|
||||
if (idleSecs <= 0) return;
|
||||
|
||||
MS_sleep(idleSecs);
|
||||
}
|
||||
|
||||
/* used by POP, SMTP, IMAP4 methods */
|
||||
void
|
||||
throttle(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *timer )
|
||||
{
|
||||
|
||||
int chokeSecs = 0;
|
||||
struct timeval exittime;
|
||||
|
||||
/* check if we need to throttle this puppy */
|
||||
if (comm->throttle <= 0)
|
||||
return;
|
||||
|
||||
/* we probably have not reached NETCLOSE yet, so we do not
|
||||
know what timer->exittime is */
|
||||
timeval_stamp(&exittime);
|
||||
|
||||
/* time to sleep = throttle - (exittime - entertime) */
|
||||
chokeSecs = comm->throttle - ( exittime.tv_sec - ptcx->starttime.tv_sec );
|
||||
|
||||
|
||||
/* if chokeSecs is negative, don't bother sleeping */
|
||||
if (chokeSecs > 0) {
|
||||
d_printf(debugfile, "throttle=%d, chokeSecs=%d\n",
|
||||
comm->throttle, chokeSecs);
|
||||
MS_idle(ptcx, chokeSecs);
|
||||
}
|
||||
|
||||
} /* end throttle */
|
||||
|
||||
/*
|
||||
* Perform the given command block
|
||||
*
|
||||
* commNum = the number of the comm (offset in loaded_comm_list[])
|
||||
*
|
||||
* returns 1
|
||||
*/
|
||||
static int
|
||||
do_command(ptcx_t ptcx, /* thread state */
|
||||
int commNum) /* command block number */
|
||||
|
||||
{
|
||||
mail_command_t *comm = &g_loaded_comm_list[commNum];
|
||||
cmd_stats_t *cmd_stats = &(ptcx->cmd_stats[commNum]);
|
||||
int cnt, cntEnd; /* loop counters */
|
||||
void *state = NULL;
|
||||
|
||||
cntEnd = comm->numLoops+1; /* transfer count +1 */
|
||||
D_PRINTF(debugfile, "do_command start t=%lu commNum=%d cntEnd=%d\n",
|
||||
time(0L), commNum, cntEnd);
|
||||
|
||||
/* Start and End are special loop cases to make summations easier */
|
||||
for (cnt = 0; cnt <= cntEnd; cnt++) {
|
||||
|
||||
if (gf_timeexpired >= EXIT_FAST) /* no more calls */
|
||||
break;
|
||||
if (gf_timeexpired >= EXIT_SOON) {
|
||||
if (!state) break; /* no shutdown to do */
|
||||
cnt = cntEnd; /* go to shutdown */
|
||||
}
|
||||
|
||||
D_PRINTF(debugfile, "do_command t=%lu count=%d of %d\n",
|
||||
time(0L), cnt, cntEnd);
|
||||
|
||||
if (0 == cnt) { /* first time */
|
||||
cmd_stats->totalcommands++; /* track command blocks trys */
|
||||
state = (*(comm->proto->cmdStart)) (ptcx, comm, cmd_stats);
|
||||
if (NULL == state) {
|
||||
D_PRINTF(debugfile, "do_command Start returned NULL\n");
|
||||
break;
|
||||
}
|
||||
if (comm->idleTime && (gf_timeexpired < EXIT_SOON)) {
|
||||
D_PRINTF(debugfile,"do_command delay %d after Setup\n",
|
||||
comm->idleTime);
|
||||
event_start(ptcx, &cmd_stats->idle);
|
||||
MS_idle(ptcx, comm->idleTime);
|
||||
event_stop(ptcx, &cmd_stats->idle);
|
||||
}
|
||||
}
|
||||
else if ((cntEnd == cnt) && comm->proto->cmdEnd) { /* last */
|
||||
(*(comm->proto->cmdEnd)) (ptcx, comm, cmd_stats, state);
|
||||
break; /* done with loop */
|
||||
}
|
||||
else if (comm->proto->cmdLoop) { /* do transfers */
|
||||
int rc;
|
||||
rc = (*(comm->proto->cmdLoop)) (ptcx, comm, cmd_stats, state);
|
||||
if (rc < 0) {
|
||||
D_PRINTF(debugfile, "do_command Loop returned error/done\n");
|
||||
cnt = cntEnd -1; /* end loop */
|
||||
}
|
||||
/* do loopDelay even if error/done */
|
||||
if (comm->loopDelay && (gf_timeexpired < EXIT_SOON)) {
|
||||
D_PRINTF(debugfile,"do_command delay %d in loop\n",
|
||||
comm->loopDelay);
|
||||
event_start(ptcx, &cmd_stats->idle);
|
||||
MS_idle(ptcx, comm->loopDelay);
|
||||
event_stop(ptcx, &cmd_stats->idle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* do blockTime even if we hit an error connecting */
|
||||
if (comm->blockTime && (gf_timeexpired < EXIT_SOON)) {
|
||||
D_PRINTF(debugfile,"do_command delay %d after Block\n",
|
||||
comm->blockTime);
|
||||
event_start(ptcx, &cmd_stats->idle);
|
||||
MS_idle(ptcx, comm->blockTime);
|
||||
event_stop(ptcx, &cmd_stats->idle);
|
||||
}
|
||||
D_PRINTF(debugfile, "do_command end t=%lu commNum=%d cntEdn=%d\n",
|
||||
time(0L), commNum, cntEnd);
|
||||
|
||||
return 1; /* return connections */
|
||||
} /* END do_command() */
|
||||
|
||||
/*
|
||||
Initialize sub process context
|
||||
*/
|
||||
int
|
||||
clientInit(ptcx_t ptcx)
|
||||
{
|
||||
ptcx->dfile = stderr;
|
||||
|
||||
if (gn_debug) {
|
||||
/* open a debug log file */
|
||||
char debug_file_name[255];
|
||||
fflush(stderr);
|
||||
if (ptcx->threadnum >= 0) {
|
||||
sprintf(debug_file_name, "%s.%d.%d",
|
||||
DEBUG_FILE, ptcx->processnum, ptcx->threadnum);
|
||||
} else {
|
||||
sprintf(debug_file_name, "%s.%d",
|
||||
DEBUG_FILE, ptcx->processnum);
|
||||
}
|
||||
ptcx->dfile = fopen(debug_file_name, "w+");
|
||||
if (ptcx->dfile == NULL) {
|
||||
/*returnerr(stderr, "Can't open debug file\n");
|
||||
return -1;*/
|
||||
gn_debug = 0;
|
||||
d_printf (stderr, "Can't open debug file. Debug mode disabled\n");
|
||||
}
|
||||
D_PRINTF(debugfile, "Running in debug mode\n");
|
||||
}
|
||||
|
||||
if (gn_record_telemetry) {
|
||||
/* open a transaction log file. */
|
||||
char log_file_name[255];
|
||||
sprintf(log_file_name, "%s.%d.%d",
|
||||
LOG_FILE, ptcx->processnum, ptcx->threadnum);
|
||||
ptcx->logfile = open(log_file_name,
|
||||
O_CREAT | O_TRUNC | O_WRONLY, 0664);
|
||||
returnerr(debugfile,"Log file is %s [%d]\n", log_file_name, ptcx->logfile);
|
||||
} else {
|
||||
ptcx->logfile = -1;
|
||||
}
|
||||
|
||||
/* Initialize random number generator */
|
||||
SRANDOM(ptcx->random_seed);
|
||||
D_PRINTF(debugfile, "Random seed: 0x%08x\n", ptcx->random_seed );
|
||||
|
||||
stats_init(&ptcx->timestat);
|
||||
|
||||
ptcx->timestat.total_num_of_commands = gn_number_of_commands;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Continuously handle command blocks until time is up
|
||||
*/
|
||||
int
|
||||
clientLoop(ptcx_t ptcx)
|
||||
{
|
||||
for(ptcx->blockCount = 0; gf_timeexpired < EXIT_SOON; ) {
|
||||
int comm_index = 0;
|
||||
|
||||
if (gn_number_of_commands > 1) {
|
||||
int ran_number;
|
||||
/* Handle the weighted distribution of commands */
|
||||
/* HAVE FILELIST */
|
||||
|
||||
D_PRINTF(debugfile, "Total weight %d\n", gn_total_weight);
|
||||
/* random number between 0 and totalweight-1 */
|
||||
ran_number = (RANDOM() % gn_total_weight);
|
||||
D_PRINTF(debugfile, "random %ld\n", ran_number );
|
||||
|
||||
/* loop through pages, find correct one
|
||||
* while ran_number is positive, decrement it
|
||||
* by the weight of the current page
|
||||
* example: ran_number is 5, pages have weights of 10 and 10
|
||||
* first iteration comm_index = 0, ran_number = -5
|
||||
* iteration halted, comm_index = 0
|
||||
*/
|
||||
comm_index = -1;
|
||||
while (ran_number >= 0) {
|
||||
comm_index++;
|
||||
D_PRINTF(debugfile, "Current command index %d: %ld - %d\n",
|
||||
comm_index, ran_number,
|
||||
g_loaded_comm_list[comm_index].weight
|
||||
);
|
||||
ran_number -= g_loaded_comm_list[comm_index].weight;
|
||||
}
|
||||
|
||||
if (comm_index >= gn_number_of_commands) { /* shouldnt happen */
|
||||
D_PRINTF(debugfile, "Command weight overrun %d %d\n",
|
||||
ran_number, gn_total_weight);
|
||||
comm_index--;
|
||||
}
|
||||
/*D_PRINTF(debugfile, "Final page index %d\n", comm_index );*/
|
||||
}
|
||||
|
||||
/* run the command */
|
||||
ptcx->connectCount += do_command(ptcx, comm_index);
|
||||
++ptcx->blockCount;
|
||||
|
||||
if (gf_timeexpired >= EXIT_SOON) break; /* done, dont throttle */
|
||||
|
||||
/* For the single processes/thread case, this should be exact */
|
||||
if ((gn_maxBlockCnt) /* check for max loops */
|
||||
&& (ptcx->blockCount >= gn_maxBlockCnt)) {
|
||||
D_PRINTF (debugfile, "Saw enough loops %d, exiting\n",
|
||||
ptcx->blockCount);
|
||||
beginShutdown (); /* indicate early exit */
|
||||
break;
|
||||
}
|
||||
|
||||
/* throttle code mikeb@netscape.com
|
||||
* keeps client from going faster than client_throttle
|
||||
* operations per minute
|
||||
*/
|
||||
if (gn_client_throttle &&
|
||||
(ptcx->timestat.endtime.tv_sec > ptcx->timestat.starttime.tv_sec)) {
|
||||
timeval_stamp(&(ptcx->timestat.endtime));
|
||||
while ( 60 * ptcx->connectCount /
|
||||
(ptcx->timestat.endtime.tv_sec - ptcx->timestat.starttime.tv_sec)
|
||||
> gn_client_throttle ) {
|
||||
D_PRINTF(debugfile, "%.2f > %d, throttling\n",
|
||||
( 60 * ptcx->connectCount /
|
||||
(ptcx->timestat.endtime.tv_sec - ptcx->timestat.starttime.tv_sec) ),
|
||||
gn_client_throttle);
|
||||
/* sleep a little */
|
||||
MS_usleep( 100 );
|
||||
} /* end while too fast */
|
||||
}
|
||||
} /* END while blockCount */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Thread of execution.
|
||||
Also works in un-threaded case.
|
||||
Initialize, do some system housekeeping, run test, housekeeping, clean up
|
||||
*/
|
||||
THREAD_RET
|
||||
clientThread(void *targ)
|
||||
{
|
||||
time_t currentTime;
|
||||
struct tm *tmptm;
|
||||
char timeStamp[DATESTAMP_LEN];
|
||||
int ret = 0;
|
||||
tcx_t *ptcx = (ptcx_t)targ;
|
||||
/*char buf[256];*/
|
||||
|
||||
if (clientInit(ptcx)) { /* should never fail */
|
||||
#ifdef USE_PTHREADS
|
||||
if (ptcx->threadnum >= 0)
|
||||
pthread_exit((void *)((1 << 16) | ptcx->threadnum));
|
||||
return NULL;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*sprintf(buf, "NOTICE: client process=%d thread=%d started\n",
|
||||
ptcx->processnum, ptcx->threadnum);
|
||||
sendOutput(ptcx->ofd, buf);*/
|
||||
|
||||
if (gn_debug) {
|
||||
/* write current time to debug file */
|
||||
time(¤tTime);
|
||||
tmptm = localtime(¤tTime);
|
||||
strftime(timeStamp, DATESTAMP_LEN, "%Y%m%d%H%M%S", tmptm);
|
||||
D_PRINTF(debugfile, "Time Stamp: %s\n", timeStamp);
|
||||
D_PRINTF(debugfile, "mailstone run dateStamp=%s\n", gs_dateStamp);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WAIT_INFINITY 100000000
|
||||
/* Tell parent we're ready */
|
||||
InterlockedIncrement(&StartedThreads);
|
||||
#else
|
||||
++StartedThreads; /* thread safe??? */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
timeval_stamp(&(ptcx->timestat.starttime));
|
||||
D_PRINTF(debugfile, "entering clientLoop\n");
|
||||
|
||||
ret = clientLoop(ptcx); /* do the work */
|
||||
|
||||
timeval_stamp(&(ptcx->timestat.endtime));
|
||||
D_PRINTF(debugfile, "Test run complete\n" );
|
||||
|
||||
/* write current time to debug file */
|
||||
time(¤tTime);
|
||||
tmptm = localtime(¤tTime);
|
||||
strftime(timeStamp, DATESTAMP_LEN, "%Y%m%d%H%M%S", tmptm);
|
||||
D_PRINTF(debugfile, "Time Stamp: %s\n", timeStamp);
|
||||
|
||||
if (gn_record_telemetry && (ptcx->logfile > 0)) {
|
||||
close(ptcx->logfile);
|
||||
ptcx->logfile = -1;
|
||||
}
|
||||
|
||||
D_PRINTF(debugfile, "client exiting.\n" );
|
||||
|
||||
if (gn_debug && ptcx->dfile) {
|
||||
fflush(ptcx->dfile);
|
||||
if (ptcx->dfile != stderr) {
|
||||
fclose(ptcx->dfile);
|
||||
ptcx->dfile = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
/*sprintf(buf, "NOTICE: client process=%d thread=%d ending\n",
|
||||
ptcx->processnum, ptcx->threadnum);
|
||||
sendOutput(ptcx->ofd, buf);*/
|
||||
|
||||
#ifdef _WIN32
|
||||
/* tell parent we're done */
|
||||
InterlockedIncrement(&FinishedThreads);
|
||||
#else /* _WIN32 */
|
||||
++FinishedThreads; /* thread safe??? */
|
||||
#ifdef USE_PTHREADS
|
||||
if (ptcx->threadnum >= 0)
|
||||
pthread_exit((void *)((ret << 16) | ptcx->threadnum));
|
||||
#endif
|
||||
return NULL;
|
||||
#endif /* _WIN32 */
|
||||
} /* END clientThread() */
|
||||
|
||||
/*
|
||||
The FORMAT format is:
|
||||
FORMAT: client=<NUMBER> <TYPE>:<NAME>\t<VALUE>
|
||||
|
||||
TYPE is one of: TIMER, PROTOCOL, LINE
|
||||
|
||||
Everything breaks down to attribute=value pairs.
|
||||
"attribute=" is literal, the listed value names the field
|
||||
|
||||
Attribute names must be unique with each timer.
|
||||
|
||||
The [] and {} indicate timers and protocols respectively.
|
||||
everything else is a literal (including whitespace).
|
||||
The protocols and timers will be expanded with simple text
|
||||
substitutions.
|
||||
|
||||
The literal text is as high in the description as possible.
|
||||
The processing splits out the values based on surrounding text.
|
||||
*/
|
||||
/*
|
||||
Output the format that the summaries will be in.
|
||||
This call the protocol specific formats, then outputs
|
||||
the complete line formats
|
||||
*/
|
||||
void
|
||||
clientSummaryFormat(int clientnum, int outfd)
|
||||
{
|
||||
char buf[SIZEOF_SUMMARYTEXT], *cp;
|
||||
char extra[96];
|
||||
protocol_t *pp;
|
||||
|
||||
sprintf (extra, "client=%d", clientnum); /* extra stuff on each line */
|
||||
|
||||
/* Define the contents of each protocol */
|
||||
for (pp=g_protocols; pp->name != NULL; ++pp) {
|
||||
if (!pp->cmdCount) continue; /* not used */
|
||||
|
||||
(pp->statsInit)(NULL, &(pp->stats), 0, 0); /* init stats (HERE?) */
|
||||
|
||||
(pp->statsFormat)(pp, extra, buf); /* output lines of format info */
|
||||
sendOutput(outfd, buf);
|
||||
}
|
||||
|
||||
/* Define the periodic update summaries */
|
||||
/* This is the most common message, so keep is as short as practical */
|
||||
cp = buf;
|
||||
sprintf(cp,
|
||||
"<FORMAT %s LINE=SUMMARY-TIME><TS %s>",
|
||||
extra,
|
||||
"client=client t=time blocks=blocks");
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
for (pp=g_protocols; pp->name != NULL; ++pp) {
|
||||
if (!pp->cmdCount) continue; /* not used */
|
||||
sprintf(cp, "\t<%s {%s}/>", pp->name, pp->name);
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
}
|
||||
strcat (cp, "</TS></FORMAT>\n");
|
||||
sendOutput(outfd, buf);
|
||||
|
||||
/* BLOCK-STATISTICS format */
|
||||
for (pp=g_protocols; pp->name != NULL; ++pp) {
|
||||
cp = buf;
|
||||
sprintf(cp,
|
||||
"<FORMAT %s LINE=BLOCK-STATISTICS-%s><BS-%s %s>",
|
||||
extra, pp->name, pp->name,
|
||||
"client=client thread=thread t=time blockID=blockID");
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
|
||||
sprintf(cp, "\t<%s {%s}/>", pp->name, pp->name);
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
sprintf (cp, "</BS-%s></FORMAT>\n", pp->name);
|
||||
sendOutput(outfd, buf);
|
||||
}
|
||||
|
||||
/* Notice Format */
|
||||
sprintf(buf,
|
||||
"<FORMAT %s LINE=NOTICE-1>%s</FORMAT>\n",
|
||||
extra,
|
||||
"<NOTICE client=client ... ");
|
||||
sendOutput(outfd, buf);
|
||||
|
||||
/* Abort Format */
|
||||
sprintf(buf,
|
||||
"<FORMAT %s LINE=NOTICE-2>%s</FORMAT>\n",
|
||||
extra,
|
||||
"<ABORT client=client ... ");
|
||||
sendOutput(outfd, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
Output the block information for each thread
|
||||
*/
|
||||
void
|
||||
clientBlockSummary(ptcx_t ptcxs, int ntcxs, int clientnum, int outfd)
|
||||
{
|
||||
time_t curtime;
|
||||
protocol_t *pp;
|
||||
int jj, kk;
|
||||
char buf[SIZEOF_SUMMARYTEXT], *bp;
|
||||
|
||||
D_PRINTF(stderr, "clientSummaryBS starting.\n" );
|
||||
curtime = time(0L);
|
||||
for (kk = 0; kk < gn_number_of_commands; ++kk) { /* all commands */
|
||||
for (jj = 0; jj < ntcxs; ++jj) { /* all threads */
|
||||
if (0 == ptcxs[jj].cmd_stats[kk].totalcommands) /* nothing */
|
||||
continue;
|
||||
pp = g_loaded_comm_list[kk].proto;
|
||||
/* output proto independent part */
|
||||
bp = buf;
|
||||
sprintf (bp,
|
||||
"<BS-%s client=%d thread=%d t=%lu blockID=%d>",
|
||||
pp->name, clientnum, jj, curtime,
|
||||
g_loaded_comm_list[kk].blockID);
|
||||
for (; *bp; ++bp); /* find end of buffer */
|
||||
|
||||
sprintf (bp,
|
||||
"\t<%s blocks=%ld ",
|
||||
pp->name,
|
||||
ptcxs[jj].cmd_stats[kk].totalcommands);
|
||||
for (; *bp; ++bp); /* find end of buffer */
|
||||
|
||||
(pp->statsOutput)(pp, &(ptcxs[jj].cmd_stats[kk]), bp);
|
||||
for (; *bp; ++bp); /* find end of buffer */
|
||||
|
||||
sprintf (bp, "/></BS-%s>\n", pp->name); /* end it */
|
||||
sendOutput(outfd, buf);
|
||||
}
|
||||
}
|
||||
D_PRINTF(stderr, "clientSummaryBS done.\n");
|
||||
}
|
||||
|
||||
/* Output the periodic activity summary */
|
||||
void
|
||||
clientTimeSummary(ptcx_t ptcxs, int ntcxs, int clientnum, int outfd)
|
||||
{
|
||||
time_t curtime;
|
||||
int blockCount = 0, connectCount = 0;
|
||||
protocol_t *pp;
|
||||
int jj, kk;
|
||||
char buf[SIZEOF_SUMMARYTEXT];
|
||||
char rqsttextbuf[SIZEOF_RQSTSTATSTEXT+1];
|
||||
static int oldThreadStarts= 0;
|
||||
static int oldThreadEnds= 0;
|
||||
|
||||
D_PRINTF(stderr, "clientTimeSummary starting.\n" );
|
||||
curtime = time(0L);
|
||||
|
||||
for (pp=g_protocols; pp->name != NULL; ++pp) { /* zero protocol stats */
|
||||
if (!pp->cmdCount) continue; /* not used */
|
||||
cmdStatsInit (&(pp->stats)); /* clear proto independent part */
|
||||
(pp->statsInit)(NULL, &(pp->stats), 0, 0); /* clear proto part */
|
||||
}
|
||||
|
||||
/* sum by protocol all commands, all threads */
|
||||
for (jj = 0; jj < ntcxs; ++jj) {
|
||||
blockCount += ptcxs[jj].blockCount;
|
||||
connectCount += ptcxs[jj].connectCount;
|
||||
for (kk = 0; kk < gn_number_of_commands; ++kk) {
|
||||
pp = g_loaded_comm_list[kk].proto;
|
||||
(pp->statsUpdate)(pp, &pp->stats, &(ptcxs[jj].cmd_stats[kk]));
|
||||
}
|
||||
}
|
||||
|
||||
/* output proto independent part */
|
||||
sprintf(buf, "<TS client=%d t=%lu blocks=%d>",
|
||||
clientnum, curtime, blockCount);
|
||||
|
||||
for (pp=g_protocols; pp->name != NULL; ++pp) { /* output proto parts */
|
||||
if (!pp->cmdCount) continue; /* not used */
|
||||
(pp->statsOutput)(pp, &pp->stats, rqsttextbuf);
|
||||
/* The \t seperates sections for report parsing */
|
||||
sprintf(&buf[strlen(buf)], "\t<%s blocks=%ld %s/>",
|
||||
pp->name, pp->stats.totalcommands,
|
||||
rqsttextbuf);
|
||||
}
|
||||
strcat(buf, "</TS>\n"); /* end it */
|
||||
sendOutput(outfd, buf);
|
||||
|
||||
/* do additional status updates */
|
||||
if (oldThreadStarts != StartedThreads) {
|
||||
sprintf(buf, "<NOTICE client=%d threadStarts=%d/>\n",
|
||||
clientnum, StartedThreads - oldThreadStarts);
|
||||
sendOutput(outfd, buf);
|
||||
oldThreadStarts = StartedThreads;
|
||||
}
|
||||
|
||||
if (oldThreadEnds != FinishedThreads) {
|
||||
sprintf(buf, "<NOTICE client=%d threadFinishes=%d/>\n",
|
||||
clientnum, FinishedThreads - oldThreadEnds);
|
||||
sendOutput(outfd, buf);
|
||||
oldThreadEnds = FinishedThreads;
|
||||
}
|
||||
|
||||
if (gn_maxerrorcnt) { /* check for max error count */
|
||||
int errors = 0;
|
||||
for (pp=g_protocols; pp->name != NULL; ++pp) { /* sum total */
|
||||
if (!pp->cmdCount) continue; /* not used */
|
||||
errors += pp->stats.combined.errs;
|
||||
}
|
||||
|
||||
if (errors > gn_maxerrorcnt) {
|
||||
returnerr (stderr,
|
||||
"<ABORT client=%d errorCount=%ld errorLimit=%ld/>\n",
|
||||
clientnum, errors, gn_maxerrorcnt);
|
||||
beginShutdown ();
|
||||
}
|
||||
}
|
||||
|
||||
if ((gn_maxBlockCnt)
|
||||
&& (blockCount >= gn_maxBlockCnt)) { /* check for max loops */
|
||||
returnerr (stderr,
|
||||
"<ABORT client=%d blockCount=%ld blockLimit=%ld/>\n",
|
||||
clientnum, blockCount, gn_maxBlockCnt);
|
||||
beginShutdown ();
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "clientTimeSummary done.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
Thread that calls clientTimeSummary at the right rate
|
||||
*/
|
||||
THREAD_RET
|
||||
summaryThread(void *targ)
|
||||
{
|
||||
ptcx_t ptcxs = (ptcx_t)targ; /* thread contexts */
|
||||
|
||||
D_PRINTF(stderr, "summaryThread starting...\n");
|
||||
|
||||
/* client threads running...dump periodic stats */
|
||||
while (gn_feedback_secs && (gf_timeexpired < EXIT_FAST)) {
|
||||
D_PRINTF(stderr, "client %d: clientTimeSummary\n", ptcxs[0].processnum);
|
||||
clientTimeSummary(ptcxs, gn_numthreads, ptcxs[0].processnum, ptcxs[0].ofd);
|
||||
D_PRINTF(stderr, "client %d: waiting %d seconds before feedback\n",
|
||||
ptcxs[0].processnum, gn_feedback_secs);
|
||||
MS_sleep(gn_feedback_secs);
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "summaryThread exiting...\n");
|
||||
|
||||
#ifdef USE_PTHREADS
|
||||
pthread_exit(0);
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize per thread context
|
||||
*/
|
||||
void
|
||||
initTcx(ptcx_t ptcx, int ofd, int pnum, int tnum)
|
||||
{
|
||||
int kk;
|
||||
ptcx->processnum = pnum;
|
||||
ptcx->threadnum = tnum;
|
||||
ptcx->random_seed = (tnum << 16) + getpid();
|
||||
ptcx->cmd_stats =
|
||||
(cmd_stats_t *)mycalloc(sizeof(cmd_stats_t)*gn_number_of_commands);
|
||||
|
||||
/* do PROTO specific init */
|
||||
for (kk = 0; kk < gn_number_of_commands; ++kk) {
|
||||
(g_loaded_comm_list[kk].proto->statsInit)
|
||||
(&g_loaded_comm_list[kk], &(ptcx->cmd_stats[kk]), pnum, tnum);
|
||||
}
|
||||
|
||||
ptcx->ofd = ofd;
|
||||
ptcx->sock = BADSOCKET_VALUE;
|
||||
}
|
||||
|
||||
void
|
||||
destroyTcx(ptcx_t ptcx)
|
||||
{
|
||||
if (ptcx->cmd_stats) {
|
||||
free(ptcx->cmd_stats);
|
||||
ptcx->cmd_stats = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static time_t bailtime;
|
||||
|
||||
/* advance directly to shutdown phase. May be called from signal handlers */
|
||||
void
|
||||
beginShutdown (void)
|
||||
{
|
||||
if (gf_timeexpired >= EXIT_SOON) return; /* already shutting down */
|
||||
|
||||
gf_timeexpired = EXIT_SOON;
|
||||
gt_shutdowntime = bailtime = time(0); /* advance end time to now */
|
||||
|
||||
/* Changing aborttime probably has no effect (wrong process) */
|
||||
gt_aborttime = gt_shutdowntime + gt_stopinterval*2*EXIT_FASTEST;
|
||||
}
|
||||
|
||||
/* This is the guts of each sub process.
|
||||
The socket for data output has already be setup.
|
||||
init context
|
||||
start threads (if possible/needed) with proper rampup delays
|
||||
wait for threads to end
|
||||
*/
|
||||
int
|
||||
clientProc(int pnum, SOCKET outfd,
|
||||
unsigned int testtime,
|
||||
unsigned int thread_stagger_usec)
|
||||
{
|
||||
int tnum;
|
||||
int ret;
|
||||
ptcx_t ptcxs; /* thread contexts */
|
||||
THREAD_ID summary_tid;
|
||||
int status;
|
||||
|
||||
|
||||
bailtime = gt_shutdowntime;
|
||||
|
||||
returnerr(stderr, "Child starting\n"); /* get our pid and time printed */
|
||||
D_PRINTF(stderr, "clientProc(%d, %d, %d) starting\n",
|
||||
pnum, testtime, thread_stagger_usec);
|
||||
|
||||
if (testtime <= 0) { /* never happens, checked in main.c */
|
||||
D_PRINTF (stderr, "ABORTING testtime=%d\n", testtime);
|
||||
return 0;
|
||||
}
|
||||
|
||||
setup_signal_handlers ();
|
||||
#ifndef _WIN32
|
||||
alarm(testtime); /* promptly notice test end */
|
||||
#endif
|
||||
|
||||
clientSummaryFormat (pnum, outfd);
|
||||
|
||||
#if defined(USE_PTHREADS) || defined(_WIN32)
|
||||
if (gn_numthreads > 0) {
|
||||
ptcxs = (ptcx_t)mycalloc(sizeof(tcx_t) * gn_numthreads);
|
||||
|
||||
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
|
||||
initTcx(&ptcxs[tnum], outfd, pnum, tnum);
|
||||
}
|
||||
|
||||
/*fprintf(stderr, "launching summary\n");*/
|
||||
if ((ret=sysdep_thread_create(&summary_tid, summaryThread,
|
||||
(void *)ptcxs)) != 0) {
|
||||
returnerr(stderr, "client %d: summary thread create failed ret=%d errno=%d: %s\n",
|
||||
pnum, ret, errno, strerror(errno));
|
||||
ptcxs[tnum].tid = 0;
|
||||
}
|
||||
/*fprintf(stderr, "summary should be running...\n");*/
|
||||
|
||||
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
|
||||
if (gf_timeexpired)
|
||||
break;
|
||||
|
||||
/* sleep between each client thread we try to start */
|
||||
if (tnum && thread_stagger_usec) {
|
||||
MS_usleep(thread_stagger_usec);
|
||||
if (gf_timeexpired)
|
||||
break;
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "client %d: thread %d testtime %d\n",
|
||||
pnum, tnum, testtime);
|
||||
|
||||
if ((ret=sysdep_thread_create(&(ptcxs[tnum].tid), clientThread,
|
||||
(void *)&ptcxs[tnum])) != 0) {
|
||||
returnerr(stderr, "client %d: thread %d create() failed ret=%d errno=%d: %s\n",
|
||||
pnum, tnum, ret, errno, strerror(errno));
|
||||
ptcxs[tnum].tid = 0;
|
||||
}
|
||||
D_PRINTF(stderr, "client %d: thread %d created with ID %d\n",
|
||||
pnum, tnum, ptcxs[tnum].tid);
|
||||
}
|
||||
|
||||
/* threads are going, but wait for them to get through setup */
|
||||
while (StartedThreads < gn_numthreads) {
|
||||
int tm = time(0);
|
||||
if (tm > bailtime) {
|
||||
++gf_timeexpired;
|
||||
bailtime += gt_stopinterval;
|
||||
}
|
||||
if (gf_timeexpired >= EXIT_SOON) /* failsafe if thread count bad */
|
||||
break;
|
||||
MS_sleep(2);
|
||||
}
|
||||
D_PRINTF(stderr, "client %d: started all threads.\n", pnum);
|
||||
|
||||
|
||||
/* Wait for all threads to exit or overtime */
|
||||
while (FinishedThreads < StartedThreads) {
|
||||
int tm = time(0);
|
||||
if (tm > bailtime) {
|
||||
++gf_timeexpired;
|
||||
bailtime += gt_stopinterval;
|
||||
#ifndef _WIN32
|
||||
if (gf_timeexpired >= EXIT_FAST) {
|
||||
returnerr (stderr, "Client signaling exit, started=%d finished=%d timeexpired=%d\n",
|
||||
StartedThreads, FinishedThreads, gf_timeexpired);
|
||||
kill (0, SIGALRM); /* wake children */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (gf_timeexpired >= EXIT_FASTEST) {
|
||||
returnerr (stderr, "Forcing sockets closed.\n");
|
||||
/* close all client sockets, to force calls to exit */
|
||||
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
|
||||
if (BADSOCKET(ptcxs[tnum].sock)) continue;
|
||||
D_PRINTF (stderr, "Closing sock=%d tnum=%d\n",
|
||||
ptcxs[tnum].sock, tnum);
|
||||
set_abortive_close(ptcxs[tnum].sock);
|
||||
NETCLOSE(ptcxs[tnum].sock);
|
||||
}
|
||||
returnerr (stderr, "Forced socket close complete.\n");
|
||||
break;
|
||||
}
|
||||
MS_sleep(1);
|
||||
}
|
||||
|
||||
|
||||
D_PRINTF (stderr, "Shutdown timeexpired=%d\n", gf_timeexpired);
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
gf_timeexpired = EXIT_FAST; /* signal summary thread to exit */
|
||||
returnerr (stderr, "Clean child shutdown\n");
|
||||
} else if (gf_timeexpired >= EXIT_FASTEST) {
|
||||
returnerr (stderr, "Forced child shutdown\n");
|
||||
} else {
|
||||
returnerr (stderr, "Accellerated child shutdown\n");
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "client %d: joining summary thread\n", pnum);
|
||||
if ((ret=sysdep_thread_join(summary_tid, &status)) != 0) {
|
||||
returnerr(stderr,
|
||||
"client %d: summary thread join failed ret=%d errno=%d: %s\n",
|
||||
pnum, ret, errno, strerror(errno));
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* do a summary now in case we hang in joins (needed?) */
|
||||
D_PRINTF(stderr, "client %d: pre-join clientTimeSummary\n", pnum);
|
||||
clientTimeSummary(ptcxs, gn_numthreads, pnum, outfd);
|
||||
|
||||
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
|
||||
D_PRINTF(stderr, "client %d: joining thread %d ID %d\n",
|
||||
pnum, tnum, ptcxs[tnum].tid);
|
||||
if (ptcxs[tnum].tid) {
|
||||
sysdep_thread_join(ptcxs[tnum].tid, &status);
|
||||
D_PRINTF(stderr, "client %d: thread %d joined ID %d, ret=%d status=%d\n",
|
||||
pnum, tnum, ptcxs[tnum].tid, ret, status);
|
||||
ptcxs[tnum].tid = 0;
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
} else
|
||||
#endif /* USE_PTHREADS || _WIN32*/
|
||||
{ /* thread un-available or 0 */
|
||||
gn_numthreads = 1;
|
||||
ptcxs = (ptcx_t)mycalloc(sizeof(tcx_t) * gn_numthreads);
|
||||
|
||||
initTcx(&ptcxs[0], outfd, pnum, -1);
|
||||
|
||||
D_PRINTF(stderr, "client %d: testtime: %d\n", pnum);
|
||||
|
||||
/* set initial data point */
|
||||
D_PRINTF(stderr, "client %d: initial clientTimeSummary\n", 0);
|
||||
clientTimeSummary(ptcxs, gn_numthreads, pnum, outfd);
|
||||
|
||||
clientThread(&ptcxs[0]);
|
||||
}
|
||||
|
||||
/* final time summary feedback */
|
||||
D_PRINTF(stderr, "client %d: final summaries\n", 0);
|
||||
clientTimeSummary(ptcxs, gn_numthreads, pnum, outfd);
|
||||
clientBlockSummary(ptcxs, gn_numthreads, pnum, outfd);
|
||||
|
||||
#if 0
|
||||
for (tnum = 0; tnum < gn_numthreads; ++tnum) { /* extra reporting */
|
||||
D_PRINTF(stderr, "client %d: thread %d stats\n", pnum, tnum);
|
||||
clientStats(&ptcxs[tnum]);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (tnum = 0; tnum < gn_numthreads; ++tnum) { /* clean up */
|
||||
D_PRINTF(stderr, "client %d: thread %d destroyed\n", pnum, tnum);
|
||||
destroyTcx(&ptcxs[tnum]);
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "child: %d done\n", pnum);
|
||||
return 0;
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
* Mike Blakely
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
/* calls for general error handling */
|
||||
|
||||
#include "bench.h"
|
||||
|
||||
#ifdef HAVE_VPRINTF
|
||||
#define VPRINTF(stderr, format, args) vfprintf((stderr), (format), (args))
|
||||
#else
|
||||
#ifdef HAVE_DOPRNT
|
||||
#define VPRINTF(stderr, format, args) _doprnt((format), (args), (stderr))
|
||||
#endif /* HAVE_DOPRNT */
|
||||
#endif /* HAVE_VPRINTF */
|
||||
|
||||
/* print an error message and exit 1 */
|
||||
void
|
||||
errexit(FILE *dfile, const char *format, ...)
|
||||
{
|
||||
time_t t=time(0L) - gt_startedtime;
|
||||
va_list args;
|
||||
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
|
||||
char buff[1024];
|
||||
int r;
|
||||
#endif
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
|
||||
/* puts as one chunk so that output doesnt get mixed up */
|
||||
r = snprintf(buff, sizeof(buff),
|
||||
"%s[%d]\tt=%lu EXITING: ", gs_thishostname, gn_myPID, t);
|
||||
vsnprintf(buff+r, sizeof(buff) - r, format, args);
|
||||
fputs (buff, stderr);
|
||||
fflush(stderr);
|
||||
|
||||
if (gn_debug && dfile && (dfile != stderr)) {
|
||||
fputs (buff, dfile);
|
||||
fflush(dfile);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr,
|
||||
"%s[%d]\tt=%lu EXITING: ", gs_thishostname, gn_myPID, t);
|
||||
VPRINTF(stderr, format, args);
|
||||
fflush(stderr);
|
||||
|
||||
if (gn_debug && dfile && (dfile != stderr)) {
|
||||
fprintf(dfile,
|
||||
"%s[%d]\tt=%lu EXITING: ", gs_thishostname, gn_myPID, t);
|
||||
VPRINTF(dfile, format, args);
|
||||
fflush(dfile);
|
||||
}
|
||||
#endif
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* This is the main feedback path for errors and status */
|
||||
/* print an error message and return -1 */
|
||||
/* Also log to the debug file if available */
|
||||
int
|
||||
returnerr(FILE *dfile, const char *format, ...)
|
||||
{
|
||||
time_t t=time(0L) - gt_startedtime;
|
||||
va_list args;
|
||||
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
|
||||
char buff[1024];
|
||||
int r;
|
||||
#endif
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
|
||||
/* puts as one chunk so that output doesnt get mixed up */
|
||||
r = snprintf(buff, sizeof(buff),
|
||||
"%s[%d]\tt=%lu: ", gs_thishostname, gn_myPID, t);
|
||||
vsnprintf(buff+r, sizeof(buff) - r, format, args);
|
||||
fputs (buff, stderr);
|
||||
fflush(stderr);
|
||||
|
||||
if (gn_debug && dfile && (dfile != stderr)) {
|
||||
fputs (buff, dfile);
|
||||
fflush(dfile);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr,
|
||||
"%s[%d]\tt=%lu: ", gs_thishostname, gn_myPID, t);
|
||||
VPRINTF(stderr, format, args);
|
||||
fflush(stderr);
|
||||
|
||||
if (gn_debug && dfile && (dfile != stderr)) {
|
||||
fprintf(dfile,
|
||||
"%s[%d]\tt=%lu: ", gs_thishostname, gn_myPID, t);
|
||||
VPRINTF(dfile, format, args);
|
||||
fflush(dfile);
|
||||
}
|
||||
#endif
|
||||
va_end(args);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* print a debug message and then flush */
|
||||
int
|
||||
d_printf(FILE *dfile, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
if (dfile) {
|
||||
fprintf(dfile, "%s: ", gs_thishostname);
|
||||
VPRINTF(dfile, format, args);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
if (dfile) fflush(dfile);
|
||||
return 0;
|
||||
}
|
||||
/* that's it */
|
||||
|
||||
/*
|
||||
Like d_printf, but for transaction logs.
|
||||
*/
|
||||
int
|
||||
t_printf(int fd, const char *buffer, size_t count, const char *format, ...)
|
||||
{
|
||||
time_t t=time(0L) - gt_startedtime;
|
||||
va_list args;
|
||||
char buff[1024];
|
||||
int r;
|
||||
|
||||
if (fd <= 0) return 0;
|
||||
|
||||
va_start(args, format);
|
||||
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
|
||||
r = snprintf(buff, sizeof(buff), /* stick in standard info */
|
||||
"<LOG t=%lu length=%d ", t, count);
|
||||
snprintf(buff + r, sizeof(buff) - r, format, args);
|
||||
strcat (buff, ">\n");
|
||||
write (fd, buff, strlen(buff));
|
||||
|
||||
if (count)
|
||||
write (fd, buffer, count); /* write the (possibly binary) data */
|
||||
|
||||
r = snprintf(buff, sizeof(buff), /* terminate entry cleanly */
|
||||
"\n</LOG t=%lu length=%d>\n", t, count);
|
||||
write (fd, buff, strlen(buff));
|
||||
#else
|
||||
if (count)
|
||||
write (fd, buffer, count); /* write the (possibly binary) data */
|
||||
#endif
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* that's it */
|
||||
|
||||
/* returns the last network error as a string */
|
||||
char *
|
||||
neterrstr(void) {
|
||||
static char buf[200];
|
||||
|
||||
#ifdef _WIN32
|
||||
sprintf(buf, "WSAGetLastError()=%d", WSAGetLastError());
|
||||
WSASetLastError(0);
|
||||
#else /* !_WIN32 */
|
||||
sprintf(buf, "errno=%d: %s", errno, strerror(errno));
|
||||
errno = 0;
|
||||
#endif /* _WIN32 */
|
||||
|
||||
return buf;
|
||||
}
|
|
@ -1,405 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
/* http.c: HTTP protocol test */
|
||||
|
||||
#include "bench.h"
|
||||
#include "http-util.h"
|
||||
|
||||
#define MAX_HTTP_RESPONSE_LEN (2*1024) /* size of sliding buffer */
|
||||
|
||||
/*
|
||||
these are protocol dependent timers for Pop, Imap, Smtp, Http
|
||||
There is one of these for every command in every thread.
|
||||
*/
|
||||
typedef struct http_stats {
|
||||
event_timer_t connect; /* initial connections */
|
||||
event_timer_t reconnect; /* re-connections */
|
||||
event_timer_t msgread; /* AKA retrieve */
|
||||
event_timer_t logout; /* AKA dis-connect */
|
||||
/* no local storage */
|
||||
} http_stats_t;
|
||||
|
||||
/* These are common to POP, IMAP, SMTP, HTTP */
|
||||
typedef struct http_command {
|
||||
resolved_addr_t hostInfo; /* Host, port, and IP cache */
|
||||
|
||||
char * httpCommand; /* Old: single HTTP command */
|
||||
|
||||
#if 0
|
||||
string_list_t getFirstCmds; /* GET commands after connect */
|
||||
string_list_t getLoopCmds; /* GET commands, each loop */
|
||||
string_list_t getLastCmds; /* GET commands before disconnect */
|
||||
#endif
|
||||
|
||||
} http_command_t;
|
||||
|
||||
/*
|
||||
State during command execution.
|
||||
*/
|
||||
typedef struct _doHTTP_state {
|
||||
int nothingHere;
|
||||
} doHTTP_state_t;
|
||||
|
||||
static void doHttpExit (ptcx_t ptcx, doHTTP_state_t *me);
|
||||
static int HttpParseNameValue (pmail_command_t cmd, char *name, char *tok);
|
||||
|
||||
/*
|
||||
Set defaults in command structure
|
||||
*/
|
||||
int
|
||||
HttpParseStart (pmail_command_t cmd,
|
||||
char *line,
|
||||
param_list_t *defparm)
|
||||
{
|
||||
param_list_t *pp;
|
||||
http_command_t *mycmd = (http_command_t *)mycalloc
|
||||
(sizeof (http_command_t));
|
||||
cmd->data = mycmd;
|
||||
|
||||
cmd->numLoops = 1; /* default 1 downloads */
|
||||
mycmd->hostInfo.portNum = HTTP_PORT; /* get default port */
|
||||
|
||||
D_PRINTF(stderr, "Http Assign defaults\n");
|
||||
/* Fill in defaults first, ignore defaults we dont use */
|
||||
for (pp = defparm; pp; pp = pp->next) {
|
||||
(void)HttpParseNameValue (cmd, pp->name, pp->value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in structure from a list of lines
|
||||
*/
|
||||
int
|
||||
HttpParseEnd (pmail_command_t cmd,
|
||||
string_list_t *section,
|
||||
param_list_t *defparm)
|
||||
{
|
||||
http_command_t *mycmd = (http_command_t *)cmd->data;
|
||||
string_list_t *sp;
|
||||
|
||||
/* Now parse section lines */
|
||||
D_PRINTF(stderr, "Http Assign section lines\n");
|
||||
/* skip first and last */
|
||||
for (sp = section->next; sp->next; sp = sp->next) {
|
||||
char *name = sp->value;
|
||||
char *tok = name + strcspn(name, " \t=");
|
||||
*tok++ = 0; /* split name off */
|
||||
tok += strspn(tok, " \t=");
|
||||
|
||||
string_tolower(name);
|
||||
tok = string_unquote(tok);
|
||||
|
||||
if (HttpParseNameValue (cmd, name, tok) < 0) {
|
||||
/* not a known attr */
|
||||
D_PRINTF(stderr,"unknown attribute '%s' '%s'\n", name, tok);
|
||||
returnerr(stderr,"unknown attribute '%s' '%s'\n", name, tok);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for some of the required command attrs */
|
||||
if (!mycmd->hostInfo.hostName) {
|
||||
D_PRINTF(stderr,"missing server for command");
|
||||
return returnerr(stderr,"missing server for command\n");
|
||||
}
|
||||
|
||||
if (!mycmd->httpCommand) {
|
||||
D_PRINTF(stderr,"missing httpcommand for HTTP");
|
||||
return returnerr(stderr,"missing httpcommand for HTTP\n");
|
||||
}
|
||||
|
||||
/* see if we can resolve the mailserver addr */
|
||||
if (resolve_addrs(mycmd->hostInfo.hostName, "tcp",
|
||||
&(mycmd->hostInfo.host_phe),
|
||||
&(mycmd->hostInfo.host_ppe),
|
||||
&(mycmd->hostInfo.host_addr),
|
||||
&(mycmd->hostInfo.host_type))) {
|
||||
return returnerr (stderr, "Error resolving hostname '%s'\n",
|
||||
mycmd->hostInfo.hostName);
|
||||
} else {
|
||||
mycmd->hostInfo.resolved = 1; /* mark the hostInfo resolved */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Parse arguments for http command
|
||||
*/
|
||||
static int
|
||||
HttpParseNameValue (pmail_command_t cmd,
|
||||
char *name,
|
||||
char *tok)
|
||||
{
|
||||
http_command_t *mycmd = (http_command_t *)cmd->data;
|
||||
D_PRINTF (stderr, "HttpParseNameValue(name='%s' value='%s')\n", name, tok);
|
||||
|
||||
/* find a home for the attr/value */
|
||||
if (cmdParseNameValue(cmd, name, tok))
|
||||
; /* done */
|
||||
else if (strcmp(name, "server") == 0)
|
||||
mycmd->hostInfo.hostName = mystrdup (tok);
|
||||
else if (strcmp(name, "portnum") == 0)
|
||||
mycmd->hostInfo.portNum = atoi(tok);
|
||||
else if (strcmp(name, "httpcommand") == 0)
|
||||
mycmd->httpCommand = mystrdup (tok);
|
||||
/*stringListAdd(&mycmd->getFirstCmds, tok);*/
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PROTOCOL specific */
|
||||
void
|
||||
HttpStatsInit(mail_command_t *cmd, cmd_stats_t *p, int procNum, int threadNum)
|
||||
{
|
||||
assert (NULL != p);
|
||||
|
||||
if (!p->data) { /* create it */
|
||||
p->data = mycalloc (sizeof (http_stats_t));
|
||||
} else { /* zero it */
|
||||
memset (p->data, 0, sizeof (http_stats_t));
|
||||
}
|
||||
|
||||
if (cmd) { /* do sub-range calulations */
|
||||
/*http_command_t *mycmd = (http_command_t *)cmd->data;
|
||||
http_stats_t *stats = (http_stats_t *)p->data;*/
|
||||
}
|
||||
}
|
||||
|
||||
/* PROTOCOL specific */
|
||||
void
|
||||
HttpStatsUpdate(protocol_t *proto,
|
||||
cmd_stats_t *sum,
|
||||
cmd_stats_t *incr)
|
||||
{
|
||||
http_stats_t *ss = (http_stats_t *)sum->data;
|
||||
http_stats_t *is = (http_stats_t *)incr->data;
|
||||
|
||||
event_sum(&sum->idle, &incr->idle);
|
||||
event_sum(&ss->connect, &is->connect);
|
||||
event_sum(&ss->msgread, &is->msgread);
|
||||
event_sum(&ss->logout, &is->logout);
|
||||
|
||||
event_reset(&incr->combined); /* figure out total */
|
||||
event_sum(&incr->combined, &incr->idle);
|
||||
event_sum(&incr->combined, &is->connect);
|
||||
event_sum(&incr->combined, &is->msgread);
|
||||
event_sum(&incr->combined, &is->logout);
|
||||
|
||||
event_sum(&sum->combined, &incr->combined); /* add our total to sum-total*/
|
||||
|
||||
sum->totalerrs += incr->totalerrs;
|
||||
sum->totalcommands += incr->totalcommands;
|
||||
}
|
||||
|
||||
/* PROTOCOL specific */
|
||||
void
|
||||
HttpStatsOutput(protocol_t *proto,
|
||||
cmd_stats_t *ptimer,
|
||||
char *buf)
|
||||
{
|
||||
char eventtextbuf[SIZEOF_EVENTTEXT];
|
||||
http_stats_t *stats = (http_stats_t *)ptimer->data;
|
||||
|
||||
*buf = 0;
|
||||
|
||||
/* BUG blocks done in clientSummary */
|
||||
event_to_text(&ptimer->combined, eventtextbuf);
|
||||
sprintf(&buf[strlen(buf)], "total=%s ", eventtextbuf);
|
||||
|
||||
event_to_text(&stats->connect, eventtextbuf);
|
||||
sprintf(&buf[strlen(buf)], "conn=%s ", eventtextbuf);
|
||||
|
||||
event_to_text(&stats->msgread, eventtextbuf);
|
||||
sprintf(&buf[strlen(buf)], "retrieve=%s ", eventtextbuf);
|
||||
|
||||
event_to_text(&stats->logout, eventtextbuf);
|
||||
sprintf(&buf[strlen(buf)], "logout=%s ", eventtextbuf);
|
||||
|
||||
event_to_text(&ptimer->idle, eventtextbuf);
|
||||
sprintf(&buf[strlen(buf)], "idle=%s ", eventtextbuf);
|
||||
|
||||
}
|
||||
|
||||
/* PROTOCOL specific */
|
||||
void
|
||||
HttpStatsFormat (protocol_t *pp,
|
||||
const char *extra, /* extra text to insert (client=) */
|
||||
char *buf)
|
||||
{
|
||||
static char *timerList[] = { /* must match order of StatsOutput */
|
||||
"total",
|
||||
"conn", "retrieve", "logout",
|
||||
"idle" };
|
||||
|
||||
char **tp;
|
||||
char *cp = buf;
|
||||
int ii;
|
||||
|
||||
/* Define the contents of each timer
|
||||
These must all the same, to that the core time functions
|
||||
can be qualified. We specify each one for reduce.pl to work right.
|
||||
*/
|
||||
|
||||
for (ii=0, tp=timerList;
|
||||
ii < (sizeof (timerList)/sizeof (timerList[0]));
|
||||
++ii, ++tp) {
|
||||
sprintf(cp, "<FORMAT %s TIMER=[%s]>%s</FORMAT>\n",
|
||||
extra, *tp,
|
||||
gs_eventToTextFormat); /* match event_to_text*/
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
}
|
||||
/* BUG blocks matches clientSummary */
|
||||
sprintf(cp, "<FORMAT %s PROTOCOL={%s}>blocks=blocks ",
|
||||
extra, pp->name);
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
for (ii=0, tp=timerList; /* same as above list (for now) */
|
||||
ii < (sizeof (timerList)/sizeof (timerList[0]));
|
||||
++ii, ++tp) {
|
||||
sprintf (cp, "%s=[%s] ", *tp, *tp);
|
||||
for (; *cp; ++cp); /* skip to the end of the string */
|
||||
}
|
||||
strcat (cp, "</FORMAT>\n");
|
||||
}
|
||||
|
||||
void *
|
||||
doHttpStart(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
|
||||
{
|
||||
doHTTP_state_t *me = (doHTTP_state_t *)mycalloc (sizeof (doHTTP_state_t));
|
||||
http_stats_t *stats = (http_stats_t *)ptimer->data;
|
||||
http_command_t *mycmd = (http_command_t *)cmd->data;
|
||||
|
||||
if (!me) return NULL;
|
||||
|
||||
if (HttpConnect(ptcx, &mycmd->hostInfo, &stats->connect) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* there is no banner or login state for HTTP */
|
||||
|
||||
return me;
|
||||
}
|
||||
|
||||
int
|
||||
doHttpLoop (
|
||||
ptcx_t ptcx,
|
||||
mail_command_t *cmd,
|
||||
cmd_stats_t *ptimer,
|
||||
void *mystate)
|
||||
{
|
||||
doHTTP_state_t *me = (doHTTP_state_t *)mystate;
|
||||
char command[MAX_COMMAND_LEN];
|
||||
char respBuffer[MAX_HTTP_RESPONSE_LEN];
|
||||
int rc;
|
||||
http_stats_t *stats = (http_stats_t *)ptimer->data;
|
||||
http_command_t *mycmd = (http_command_t *)cmd->data;
|
||||
|
||||
if (BADSOCKET(ptcx->sock)) { /* re-connect if needed */
|
||||
rc = HttpConnect(ptcx, &mycmd->hostInfo, &stats->connect);
|
||||
if (rc == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* send the HTTP command */
|
||||
|
||||
strcpy (command, mycmd->httpCommand);
|
||||
strcat (command, " HTTP/1.0\r\n");
|
||||
/* other headers go here... */
|
||||
strcat(command, "\r\n");
|
||||
rc = HttpCommandResponse(ptcx, cmd, mystate,
|
||||
&mycmd->hostInfo, &stats->connect,
|
||||
&stats->msgread,
|
||||
command, respBuffer,
|
||||
sizeof(respBuffer), NULL);
|
||||
if (rc == 0) {
|
||||
doHttpExit (ptcx, me);
|
||||
return -1;
|
||||
}
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->msgread.errs++;
|
||||
}
|
||||
doHttpExit (ptcx, me);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
doHttpEnd(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
|
||||
{
|
||||
doHTTP_state_t *me = (doHTTP_state_t *)mystate;
|
||||
http_stats_t *stats = (http_stats_t *)ptimer->data;
|
||||
|
||||
if (BADSOCKET(ptcx->sock)) return; /* closed by previous error */
|
||||
|
||||
#if 0
|
||||
int rc;
|
||||
char command[MAX_COMMAND_LEN];
|
||||
char respBuffer[MAX_RESPONSE_LEN];
|
||||
|
||||
/* send HTTP QUIT equivalent */
|
||||
sprintf(command, "QUIT%s", CRLF);
|
||||
event_start(ptcx, &stats->logout);
|
||||
rc = doHttpCommandResponse(ptcx, ptcx->sock, command, respBuffer);
|
||||
event_stop(ptcx, &stats->logout);
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->logout.errs++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
event_start(ptcx, &stats->logout);
|
||||
NETCLOSE(ptcx->sock); ptcx->sock = BADSOCKET_VALUE;
|
||||
event_stop(ptcx, &stats->logout);
|
||||
#endif
|
||||
|
||||
doHttpExit (ptcx, me);
|
||||
}
|
||||
|
||||
void
|
||||
doHttpExit (ptcx_t ptcx, doHTTP_state_t *me)
|
||||
{
|
||||
if (!BADSOCKET(ptcx->sock))
|
||||
NETCLOSE(ptcx->sock);
|
||||
ptcx->sock = BADSOCKET_VALUE;
|
||||
|
||||
myfree (me);
|
||||
}
|
1021
mstone/src/imap4.c
1021
mstone/src/imap4.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,974 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
/*
|
||||
main.c handles all the initialization and then forks off sub processes.
|
||||
*/
|
||||
|
||||
#include "bench.h"
|
||||
|
||||
/* really globalize variables */
|
||||
volatile int gf_timeexpired = 0;
|
||||
time_t gt_testtime = 0; /* time of test, in seconds */
|
||||
time_t gt_startedtime = 0; /* when we started */
|
||||
volatile time_t gt_shutdowntime = 0; /* startedtime + testtime */
|
||||
time_t gt_stopinterval = 0; /* MAX (ramptime/5, 10) */
|
||||
time_t gt_aborttime = 0; /* startedtime + testtime + ramptime*/
|
||||
|
||||
int gn_record_telemetry = 0;
|
||||
int gn_total_weight = 0;
|
||||
int gn_client_throttle = 0;
|
||||
int gn_maxerrorcnt = 0;
|
||||
int gn_maxBlockCnt = 0;
|
||||
int gn_numprocs = 0;
|
||||
int gn_numthreads = 0;
|
||||
int gn_debug = 0;
|
||||
int gn_feedback_secs = 5;
|
||||
int gf_abortive_close = 0;
|
||||
int gn_number_of_commands = 0;
|
||||
int gf_imapForceUniqueness = 0;
|
||||
char gs_dateStamp[DATESTAMP_LEN];
|
||||
char gs_thishostname[MAXHOSTNAMELEN+10] = "";
|
||||
char *gs_parsename = gs_thishostname; /* name used during parsing */
|
||||
pid_t gn_myPID = 0;
|
||||
mail_command_t *g_loaded_comm_list; /* actually a dynamic array */
|
||||
|
||||
protocol_t g_protocols[] = { /* array of protocol information */
|
||||
{
|
||||
"SMTP",
|
||||
SmtpParseStart,
|
||||
SmtpParseEnd,
|
||||
sendSMTPStart,
|
||||
sendSMTPLoop,
|
||||
sendSMTPEnd,
|
||||
pishStatsFormat,
|
||||
pishStatsInit,
|
||||
pishStatsUpdate,
|
||||
pishStatsOutput,
|
||||
},
|
||||
{
|
||||
"POP3",
|
||||
Pop3ParseStart,
|
||||
Pop3ParseEnd,
|
||||
doPop3Start,
|
||||
doPop3Loop,
|
||||
doPop3End,
|
||||
pishStatsFormat,
|
||||
pishStatsInit,
|
||||
pishStatsUpdate,
|
||||
pishStatsOutput,
|
||||
},
|
||||
{
|
||||
"IMAP4",
|
||||
Imap4ParseStart,
|
||||
Imap4ParseEnd,
|
||||
doImap4Start,
|
||||
doImap4Loop,
|
||||
doImap4End,
|
||||
pishStatsFormat,
|
||||
pishStatsInit,
|
||||
pishStatsUpdate,
|
||||
pishStatsOutput,
|
||||
},
|
||||
{
|
||||
"HTTP",
|
||||
HttpParseStart,
|
||||
HttpParseEnd,
|
||||
doHttpStart,
|
||||
doHttpLoop,
|
||||
doHttpEnd,
|
||||
HttpStatsFormat,
|
||||
HttpStatsInit,
|
||||
HttpStatsUpdate,
|
||||
HttpStatsOutput,
|
||||
},
|
||||
{
|
||||
"WMAP",
|
||||
WmapParseStart,
|
||||
WmapParseEnd,
|
||||
doWmapStart,
|
||||
doWmapLoop,
|
||||
doWmapEnd,
|
||||
WmapStatsFormat,
|
||||
WmapStatsInit,
|
||||
WmapStatsUpdate,
|
||||
WmapStatsOutput,
|
||||
},
|
||||
{
|
||||
NULL, /* terminate the list */
|
||||
},
|
||||
};
|
||||
|
||||
/* End of globals */
|
||||
|
||||
static time_t ramptime = 0;
|
||||
|
||||
static char mailmaster[MAXHOSTNAMELEN];
|
||||
static NETPORT listenport = 0;
|
||||
static char *commandsfilename = NULL;
|
||||
static int f_usestdin = 0;
|
||||
#if 0
|
||||
static struct hostent mailserv_phe, mailmast_phe;
|
||||
static struct protoent mailserv_ppe, mailmast_ppe;
|
||||
static unsigned long mailserv_addr, mailmast_addr;
|
||||
static short mailserv_type, mailmast_type; /* socket type */
|
||||
#endif
|
||||
|
||||
static void
|
||||
usage(const char *progname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options] -n <clients> -t <time> <-s | -u <commandFile>>\n\n",
|
||||
progname);
|
||||
fprintf(stderr, " required parameters:\n");
|
||||
fprintf(stderr, " -n numprocs number of clients processes to run [1-%d]\n",
|
||||
MAXPROCSPERNODE);
|
||||
fprintf(stderr, " -t testtime test duration (mins) or #[hmsd]\n");
|
||||
fprintf(stderr, " -s use stdin for commands\n");
|
||||
fprintf(stderr, " -u commandlist file for commands\n\n");
|
||||
|
||||
fprintf(stderr, " options:\n");
|
||||
fprintf(stderr, " -h help - this message\n\n");
|
||||
fprintf(stderr, " -H name hostname for parsing HOSTS=\n");
|
||||
fprintf(stderr, " -A use abortive close\n");
|
||||
fprintf(stderr, " -T opsperhour client throttle\n");
|
||||
fprintf(stderr, " -f summpersec frequency to send summary results\n");
|
||||
fprintf(stderr, " -d debug\n");
|
||||
fprintf(stderr, " -D datestamp assign a datestamp\n");
|
||||
fprintf(stderr, " -N numthreads number of clients threads per process\n");
|
||||
fprintf(stderr, " -m maxErrorCnt threshold to force test abort\n");
|
||||
fprintf(stderr, " -M maxBlockCnt number of blocks to run\n");
|
||||
fprintf(stderr, " -R ramptime test rampup time (secs)\n");
|
||||
fprintf(stderr, " -v print version\n");
|
||||
fprintf(stderr, " -r record all transactions\n\n");
|
||||
exit(1);
|
||||
} /* END usage() */
|
||||
|
||||
void
|
||||
parseArgs(int argc, char **argv)
|
||||
{
|
||||
int getoptch;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
/*
|
||||
* PARSE THE COMMAND LINE OPTIONS
|
||||
*/
|
||||
|
||||
while((getoptch =
|
||||
getopt(argc,argv,"hf:H:T:t:u:c:m:M:n:N:R:D:Adrsv")) != EOF)
|
||||
{
|
||||
switch(getoptch)
|
||||
{
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
break;
|
||||
case 'H': /* name for parsing */
|
||||
gs_parsename = mystrdup(optarg);
|
||||
break;
|
||||
case 'A':
|
||||
gf_abortive_close = 1;
|
||||
break;
|
||||
case 'T':
|
||||
/* client throttles to ops/hour */
|
||||
gn_client_throttle = atoi(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
/* feedback frequency in seconds */
|
||||
gn_feedback_secs = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
gn_debug = 1;
|
||||
break;
|
||||
case 'D':
|
||||
strcpy(gs_dateStamp, optarg);
|
||||
break;
|
||||
case 'm':
|
||||
gn_maxerrorcnt = atoi(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
gn_maxBlockCnt = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
gn_numprocs = atoi(optarg);
|
||||
break;
|
||||
case 'N':
|
||||
gn_numthreads = atoi(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
commandsfilename = mystrdup(optarg);
|
||||
break;
|
||||
case 's':
|
||||
f_usestdin = 1;
|
||||
break;
|
||||
case 't':
|
||||
gt_testtime = time_atoi(optarg);
|
||||
break;
|
||||
case 'R':
|
||||
ramptime = time_atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
fprintf(stderr, "Netscape " MAILCLIENT_VERSION "\n");
|
||||
fprintf(stderr, "Copyright (c) Netscape Communications Corporation 1997, 1998, 1999\n");
|
||||
exit(1);
|
||||
break;
|
||||
case 'r':
|
||||
gn_record_telemetry = 1;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define SIZEOF_NTOABUF ((3+1)*4)
|
||||
|
||||
char *
|
||||
safe_inet_ntoa(struct in_addr ina, char *psz)
|
||||
{
|
||||
sprintf(psz,"%d.%d.%d.%d",
|
||||
((unsigned char *)&ina.s_addr)[0],
|
||||
((unsigned char *)&ina.s_addr)[1],
|
||||
((unsigned char *)&ina.s_addr)[2],
|
||||
((unsigned char *)&ina.s_addr)[3]);
|
||||
return psz;
|
||||
}
|
||||
|
||||
/* look up the host name and protocol
|
||||
* called from each protocol (via connectSocket)
|
||||
*/
|
||||
|
||||
int
|
||||
resolve_addrs(char *host,
|
||||
char *protocol,
|
||||
struct hostent *host_phe,
|
||||
struct protoent *proto_ppe,
|
||||
unsigned long *addr,
|
||||
short *type)
|
||||
{
|
||||
struct hostent *phe;
|
||||
struct protoent *ppe;
|
||||
#ifdef USE_PTHREADS
|
||||
#ifdef USE_GETHOSTBYNAME_R
|
||||
struct hostent he;
|
||||
struct protoent pe;
|
||||
char buf[512];
|
||||
int h_err;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* if IP address given, convert to internal form */
|
||||
if (host[0] >= '0' && host[0] <= '9') {
|
||||
*addr = inet_addr(host);
|
||||
if (*addr == INADDR_NONE)
|
||||
return(returnerr(stderr,"Invalid IP address %s\n", host));
|
||||
|
||||
} else {
|
||||
/* look up by name */
|
||||
#ifdef USE_GETHOSTBYNAME_R
|
||||
phe = gethostbyname_r(host, &he, buf, sizeof(buf), &h_err);
|
||||
errno = h_err;
|
||||
#else
|
||||
phe = gethostbyname(host);
|
||||
#endif
|
||||
|
||||
if (phe == NULL)
|
||||
{
|
||||
D_PRINTF(stderr, "Gethostbyname failed: %s", neterrstr() );
|
||||
return(returnerr(stderr,"Can't get %s host entry\n", host));
|
||||
}
|
||||
memcpy(host_phe, phe, sizeof(struct hostent));
|
||||
memcpy((char *)addr, phe->h_addr, sizeof(*addr));
|
||||
}
|
||||
|
||||
/* Map protocol name to protocol number */
|
||||
#ifdef USE_GETPROTOBYNAME_R
|
||||
ppe = getprotobyname_r(protocol, &pe, buf, sizeof(buf));
|
||||
#else
|
||||
ppe = getprotobyname(protocol);
|
||||
#endif
|
||||
|
||||
if (ppe == 0)
|
||||
{
|
||||
D_PRINTF(stderr, "protobyname returned %d\n", ppe );
|
||||
return(returnerr(stderr,"Can't get %s protocol entry\n",protocol));
|
||||
}
|
||||
memcpy(proto_ppe, ppe, sizeof(struct protoent));
|
||||
|
||||
/* D_PRINTF(stderr, "Protocol number %d\n", ppe->p_proto ); */
|
||||
|
||||
/* Use protocol to choose a socket type */
|
||||
if (strcmp(protocol,"udp") == 0)
|
||||
{
|
||||
*type = SOCK_DGRAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
*type = SOCK_STREAM;
|
||||
/* D_PRINTF(stderr, "Choosing SOCK_STREAM %d type %d %s\n",
|
||||
SOCK_STREAM, *type, neterrstr() ); */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* connect to a socket given the hostname and protocol */
|
||||
SOCKET
|
||||
connectSocket(ptcx_t ptcx,
|
||||
resolved_addr_t *hostInfo,
|
||||
char *protocol)
|
||||
{
|
||||
struct sockaddr_in sin; /* an Internet endpoint address */
|
||||
SOCKET s; /* socket descriptor */
|
||||
int type; /* socket type */
|
||||
short proto;
|
||||
int returnval; /* temporary return value */
|
||||
char ntoa_buf[SIZEOF_NTOABUF];
|
||||
|
||||
D_PRINTF(debugfile, "Beginning connectSocket; host=%s port=%d proto=%s\n",
|
||||
hostInfo->hostName, hostInfo->portNum, protocol );
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
memset((char *)&sin, 0, sizeof(sin));
|
||||
D_PRINTF(debugfile, "Zeroed address structure\n" );
|
||||
|
||||
sin.sin_port = htons(hostInfo->portNum);
|
||||
D_PRINTF(debugfile, "Set port number %d\n", hostInfo->portNum);
|
||||
|
||||
/* check if we've resolved this already */
|
||||
if ((hostInfo) && (hostInfo->resolved)) {
|
||||
sin.sin_addr.S_ADDR = hostInfo->host_addr;
|
||||
sin.sin_family = PF_INET;
|
||||
proto = hostInfo->host_ppe.p_proto;
|
||||
type = hostInfo->host_type;
|
||||
} else {
|
||||
struct hostent host_phe;
|
||||
struct protoent host_ppe;
|
||||
unsigned long host_addr;
|
||||
short host_type; /* socket type */
|
||||
|
||||
if (resolve_addrs(hostInfo->hostName, "tcp",
|
||||
&host_phe, &host_ppe, &host_addr, &host_type)) {
|
||||
return returnerr(debugfile,"Can't resolve hostname %s in get()\n",
|
||||
hostInfo->hostName);
|
||||
}
|
||||
sin.sin_addr.S_ADDR = host_addr;
|
||||
sin.sin_family = PF_INET;
|
||||
proto = host_ppe.p_proto;
|
||||
type = host_type;
|
||||
}
|
||||
|
||||
/* Allocate a socket */
|
||||
s = socket(PF_INET, type, proto);
|
||||
|
||||
if (BADSOCKET(s))
|
||||
{
|
||||
D_PRINTF(debugfile, "Can't create socket: %s\n",neterrstr() );
|
||||
return BADSOCKET_VALUE;
|
||||
}
|
||||
|
||||
/* Connect the socket */
|
||||
D_PRINTF(debugfile, "Trying to connect %d with size %d\n",
|
||||
s, sizeof(sin));
|
||||
D_PRINTF(debugfile, "Address is family %d, port %d, addr %s\n",
|
||||
sin.sin_family, ntohs(sin.sin_port),
|
||||
safe_inet_ntoa(sin.sin_addr, ntoa_buf) );
|
||||
|
||||
returnval = connect(s, (struct sockaddr *)&sin, sizeof(sin));
|
||||
|
||||
if (returnval < 0) {
|
||||
int err = GET_ERROR; /* preserve the error code */
|
||||
|
||||
D_PRINTF(debugfile, "Can't connect: %s\n", neterrstr() );
|
||||
NETCLOSE(s);
|
||||
|
||||
SET_ERROR(err);
|
||||
return BADSOCKET_VALUE;
|
||||
}
|
||||
|
||||
/* all done, returning socket descriptor */
|
||||
D_PRINTF(debugfile, "Returning %d from connectSocket call\n", s );
|
||||
return(s);
|
||||
|
||||
} /* END connectSocket() */
|
||||
|
||||
int
|
||||
set_abortive_close(SOCKET sock)
|
||||
{
|
||||
struct linger linger_opt;
|
||||
|
||||
linger_opt.l_onoff = 1;
|
||||
linger_opt.l_linger = 0;
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_LINGER,
|
||||
(char *) &linger_opt, sizeof(linger_opt)) < 0) {
|
||||
returnerr(stderr, "Couldn't set SO_LINGER = 0\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
initializeCommands(char *cfilename)
|
||||
{
|
||||
char *cbuf = NULL;
|
||||
int cbuflen = 0;
|
||||
int cbufalloced = 0;
|
||||
int ret;
|
||||
FILE *cfile;
|
||||
|
||||
D_PRINTF(stderr, "initializeCommands(%s)\n",
|
||||
cfilename ? cfilename : "STDIN");
|
||||
|
||||
if (cfilename == NULL || strlen(cfilename) == 0) {
|
||||
cfile = stdin;
|
||||
cfilename = "stdin";
|
||||
} else {
|
||||
if ((cfile = fopen(cfilename, "r")) == NULL) {
|
||||
D_PRINTF(stderr, "Cannot open commands file %s: errno=%d: %s\n",
|
||||
cfilename, errno, strerror(errno));
|
||||
errexit(stderr, "Cannot open commands file %s: errno=%d: %s\n",
|
||||
cfilename, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
#define CMDBUF_INCR 4096 /* longest allowed line */
|
||||
|
||||
while (!feof(cfile)) { /* read file in to char array */
|
||||
if ((cbuflen + CMDBUF_INCR + 1) > cbufalloced) { /* grow array */
|
||||
cbufalloced += CMDBUF_INCR;
|
||||
cbuf = (char *)myrealloc(cbuf, cbufalloced+1);
|
||||
cbuf[cbuflen] = '\0';
|
||||
}
|
||||
ret = fread(cbuf+cbuflen, 1, CMDBUF_INCR, cfile);
|
||||
if (ret < 0) {
|
||||
D_PRINTF(stderr, "Error reading commands file %s: errno=%d: %s\n",
|
||||
cfilename, errno, strerror(errno));
|
||||
errexit(stderr, "Error reading commands file %s: errno=%d: %s\n",
|
||||
cfilename, errno, strerror(errno));
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
cbuflen += ret;
|
||||
cbuf[cbuflen] = '\0';
|
||||
}
|
||||
|
||||
if (cfile != stdin)
|
||||
fclose(cfile);
|
||||
|
||||
/* D_PRINTF(stderr, "Got commands len=%d:\n%s\n", cbuflen, cbuf); */
|
||||
|
||||
/* Read commands into structure, make sure we have all req arguments */
|
||||
if ((gn_total_weight = load_commands(cbuf)) < 0) {
|
||||
D_PRINTF(stderr, "could not load %s\n", cfilename);
|
||||
errexit(stderr, "Could not load command file\n");
|
||||
}
|
||||
if (0 == gn_total_weight) {
|
||||
D_PRINTF(stderr, "No commands found for this host in %s\n", cfilename);
|
||||
errexit(stderr, "No command for current host in command file\n");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
readwriteStream(int ii, int fdin, int fdout)
|
||||
{
|
||||
char buf[MAX (8192, 2*SIZEOF_SUMMARYTEXT+1)], *cp;
|
||||
int res;
|
||||
int toread = sizeof(buf)-1;
|
||||
int towrite;
|
||||
|
||||
D_PRINTF(stderr, "readwriteStream(%d,%d,%d)\n", ii, fdin, fdout);
|
||||
|
||||
/* structured as a while() for future nonblocking style */
|
||||
while (toread) {
|
||||
errno = 0;
|
||||
res = NETREAD(fdin, buf, sizeof(buf)-1);
|
||||
D_PRINTF(stderr, "read %d bytes from client %d\n", res, ii);
|
||||
if (res == 0) {
|
||||
return -1; /* EOF unless O_NDELAY */
|
||||
} else if (res < 0) {
|
||||
if (errno == EINTR || errno == EINTR) {
|
||||
return 0; /* go back to the poll loop to service others */
|
||||
}
|
||||
|
||||
fprintf(stderr, "readwriteStream(%d,%d,%d) error reading: errno=%d: %s\n",
|
||||
ii, fdin, fdout, errno, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
/* TODO: ...can do more data reduction here... */
|
||||
|
||||
toread -= res;
|
||||
|
||||
cp = buf;
|
||||
towrite = res;
|
||||
buf[towrite] = '\0';
|
||||
/*D_PRINTF(stderr, "writing %d bytes to %d [%s]\n", towrite, fdout, buf);*/
|
||||
D_PRINTF(stderr, "writing %d bytes to %d\n", towrite, fdout);
|
||||
while (towrite) {
|
||||
res = write(fdout, cp, towrite);
|
||||
D_PRINTF(stderr, "wrote %d bytes to %d\n", res, fdout);
|
||||
if (res <= 0) {
|
||||
D_PRINTF(stderr, "error writing to %d: errno=%d: %s\n", fdout, errno, strerror(errno));
|
||||
} else {
|
||||
towrite -= res;
|
||||
cp += res;
|
||||
}
|
||||
}
|
||||
}
|
||||
toread = 0; /* just read one chunk at a time for now... */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DIRECT_OUT /* report directly to stdout */
|
||||
|
||||
int
|
||||
readwriteChildren(pccx_t pccxs)
|
||||
{
|
||||
while (readwriteStream(0, pccxs[0].socket, 1) >= 0)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
/* This is where the master process merges output and waits for
|
||||
the spawned processes to exit.
|
||||
Note that no alarm has been set. We never wait very long in poll.
|
||||
*/
|
||||
int
|
||||
readwriteChildren(pccx_t pccxs)
|
||||
{
|
||||
struct pollfd *pfds;
|
||||
int nfds;
|
||||
int ii;
|
||||
|
||||
/*
|
||||
* Wait for all children to exit.
|
||||
*/
|
||||
nfds=0;
|
||||
pfds = (struct pollfd *)mycalloc(sizeof(struct pollfd)*gn_numprocs);
|
||||
for (ii=0; ii < gn_numprocs; ++ii) {
|
||||
if (pccxs[ii].socket != -1) {
|
||||
pfds[nfds].fd = pccxs[ii].socket;
|
||||
++nfds;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
while (nfds > 0) {
|
||||
int ret, closethisfd;
|
||||
if (time(0L) >= gt_aborttime) {
|
||||
D_PRINTF (stderr, "Time is up. Signalling exit %d\n",
|
||||
gf_timeexpired);
|
||||
gf_timeexpired = EXIT_FASTEST; /* signal clean up and exit */
|
||||
break; /* just get out of here */
|
||||
}
|
||||
for (ii=0; ii < nfds; ++ii) {
|
||||
pfds[ii].events = POLLIN;
|
||||
pfds[ii].revents = 0;
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "entering poll(nfds=%d)\n", nfds);
|
||||
ret = poll(pfds, nfds, 5*1000);
|
||||
D_PRINTF(stderr, "back from poll, ret=%d\n", ret);
|
||||
|
||||
if (ret == 0)
|
||||
continue;
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
|
||||
fprintf(stderr, "poll error: errno=%d: %s\n", errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (ii = 0; ii < nfds; ++ii) {
|
||||
closethisfd = 0;
|
||||
|
||||
if (pfds[ii].revents) {
|
||||
D_PRINTF(stderr, "poll says stdout fd=%d for client=%d is 0x%02x\n",
|
||||
pfds[ii].fd, ii, pfds[ii].revents);
|
||||
}
|
||||
|
||||
if (pfds[ii].revents & POLLIN) {
|
||||
if (readwriteStream(ii, pfds[ii].fd, 1) == -1) {
|
||||
closethisfd = 1;
|
||||
}
|
||||
} else if (pfds[ii].revents & (POLLHUP | POLLERR | POLLNVAL)) {
|
||||
if (pfds[ii].revents & POLLHUP)
|
||||
D_PRINTF(stderr, "POLLHUP for stdout fd=%d for client=%d!\n",
|
||||
pfds[ii].fd, ii);
|
||||
closethisfd = 1;
|
||||
}
|
||||
|
||||
if (closethisfd) {
|
||||
D_PRINTF(stderr, "closing for slot=%d fd=%d nfds=%d\n",
|
||||
ii, pfds[ii].fd, nfds);
|
||||
NETCLOSE(pfds[ii].fd);
|
||||
|
||||
--nfds; /* shrink poll array */
|
||||
/* NOTE: this re-orders the array */
|
||||
if (ii != nfds) { /* move last one into old spot */
|
||||
pfds[ii].fd = pfds[nfds].fd;
|
||||
pfds[ii].events = pfds[nfds].events;
|
||||
pfds[ii].revents = pfds[nfds].revents;
|
||||
--ii; /* check moved entry on the next loop */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nfds > 0) {
|
||||
d_printf (stderr,
|
||||
"WARNING: Exiting with open clients nfds=%d time=%lu shutdowntime=%lu\n",
|
||||
nfds, time(0L), gt_shutdowntime);
|
||||
for (ii = 0; ii < nfds; ++ii) { /* close socket to make clients die */
|
||||
D_PRINTF(stderr, "closing for slot=%d fd=%d\n", ii, pfds[ii].fd);
|
||||
NETCLOSE(pfds[ii].fd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* This is where each sub process starts */
|
||||
THREAD_RET
|
||||
launchChild(void *targ)
|
||||
{
|
||||
SOCKET clientsock;
|
||||
struct sockaddr_in saddr; /* server address */
|
||||
struct linger linger_opt;
|
||||
unsigned int testtimeleft;
|
||||
int ret;
|
||||
unsigned int thread_stagger_usec = 1000; /* 1000/sec */
|
||||
int pnum = (int)targ;
|
||||
|
||||
gn_myPID = getpid();
|
||||
if (ramptime) {
|
||||
/* comvert to microseconds */
|
||||
if (gn_numthreads > 0) {
|
||||
/* force intermediate result to double to avoid overflow */
|
||||
thread_stagger_usec = (unsigned int)((ramptime * (double)USECINSEC) / gn_numthreads);
|
||||
} else {
|
||||
thread_stagger_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((clientsock=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
errexit(stderr, "child socket(): %s\n", neterrstr());
|
||||
}
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_addr.S_ADDR = inet_addr("127.0.0.1");
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = listenport;
|
||||
|
||||
if (connect(clientsock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
|
||||
NETCLOSE(clientsock);
|
||||
errexit(stderr, "child connect(): %s\n", neterrstr());
|
||||
}
|
||||
#if 1
|
||||
linger_opt.l_onoff = 1;
|
||||
linger_opt.l_linger = 60;
|
||||
|
||||
if (setsockopt(clientsock, SOL_SOCKET, SO_LINGER, (char *) &linger_opt, sizeof(linger_opt)) < 0) {
|
||||
NETCLOSE(clientsock);
|
||||
errexit(stderr, "child setsockopt(): %s\n", neterrstr());
|
||||
}
|
||||
#endif
|
||||
D_PRINTF(stderr, "child %d: using socket %d\n", pnum, clientsock);
|
||||
|
||||
|
||||
#if 0
|
||||
unsigned int fork_stagger_usec = 10000; /* 100/sec */
|
||||
if (pnum) {
|
||||
D_PRINTF(stderr, "child %d: delaying %d secs\n",
|
||||
pnum, USECS_2_SECS(pnum * fork_stagger_usec));
|
||||
MS_usleep(pnum * fork_stagger_usec);
|
||||
}
|
||||
#endif
|
||||
|
||||
testtimeleft = gt_shutdowntime - time(0L);
|
||||
|
||||
D_PRINTF(stderr, "child %d: proceeding for %d remaining seconds\n",
|
||||
pnum, testtimeleft);
|
||||
|
||||
if (testtimeleft > 0) {
|
||||
/* This is where the test gets run */
|
||||
#ifndef DIRECT_OUT
|
||||
ret = clientProc(pnum, clientsock,
|
||||
testtimeleft, thread_stagger_usec);
|
||||
#else
|
||||
ret = clientProc(pnum, fileno(stdout),
|
||||
testtimeleft, thread_stagger_usec);
|
||||
#endif
|
||||
} else {
|
||||
D_PRINTF(stderr, "child %d: Too late to start! shudowntime=%lu now=%lu\n",
|
||||
pnum, testtimeleft, time(0L));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "child %d: closing logging socket\n", pnum);
|
||||
NETCLOSE(clientsock);
|
||||
|
||||
#ifndef _WIN32
|
||||
return((void *)ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wait for childred to exit (after readwritechildren returns).
|
||||
*/
|
||||
int
|
||||
waitChildren(void)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int pid;
|
||||
int status;
|
||||
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
alarm(gt_stopinterval); /* dont wait forever */
|
||||
pid = wait(&status);
|
||||
if (pid == -1) {
|
||||
if (errno == ECHILD) {
|
||||
break; /* none left. finished */
|
||||
}
|
||||
if (errno == EINTR) { /* alarm went off */
|
||||
if (time(0L) > (gt_aborttime+(EXIT_FAST*gt_stopinterval))) {
|
||||
d_printf (stderr,
|
||||
"WARNING: Aborting wait for children!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (WIFSIGNALED (status)) { /* show error exits */
|
||||
d_printf (stderr, "Client pid %d died with signal %d\n",
|
||||
pid, WTERMSIG(status));
|
||||
} else {
|
||||
D_PRINTF(stderr, "Client pid %d: status: %d errno=%d: %s\n",
|
||||
pid, status, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ii;
|
||||
struct tm *tmptm;
|
||||
time_t currentTime;
|
||||
#ifdef _WIN32
|
||||
int err;
|
||||
WSADATA WSAData;
|
||||
#endif
|
||||
int ret;
|
||||
int pid=0;
|
||||
pccx_t pccxs; /* client process contexts */
|
||||
SOCKET serversock;
|
||||
struct sockaddr_in saddr; /* server address */
|
||||
struct sockaddr_in caddr; /* client address */
|
||||
int addr_len;
|
||||
char ntoabuf[SIZEOF_NTOABUF];
|
||||
|
||||
#ifdef _WIN32
|
||||
//MessageBeep(~0U); /* announce our existence */
|
||||
|
||||
err = WSAStartup(MAKEWORD(1,1), &WSAData);
|
||||
if (err != 0) {
|
||||
errexit(stderr, "Error in WSAStartup()\n");
|
||||
}
|
||||
|
||||
atexit(sock_cleanup);
|
||||
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
gn_myPID = getpid();
|
||||
gethostname(gs_thishostname, sizeof(gs_thishostname)-1);
|
||||
|
||||
memset(mailmaster, 0, sizeof(mailmaster));
|
||||
memset(gs_dateStamp, 0, DATESTAMP_LEN*sizeof(char));
|
||||
|
||||
parseArgs(argc, argv);
|
||||
|
||||
returnerr(stderr, MAILCLIENT_VERSION "\n");
|
||||
returnerr(stderr, "procs=%d threads=%d seconds=%d ramptime=%d...\n",
|
||||
gn_numprocs, gn_numthreads , gt_testtime, ramptime);
|
||||
if (ramptime > gt_testtime) {
|
||||
returnerr (stderr, "RampTime %d longer than TestTime %d. Adjusting.\n",
|
||||
ramptime, gt_testtime);
|
||||
ramptime = gt_testtime;
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "Running in debug mode\n\n" );
|
||||
|
||||
/* print the command line */
|
||||
if (gn_debug) {
|
||||
for (ii = 0; ii < argc; ii++)
|
||||
fprintf(stderr, "%s ", argv[ii] );
|
||||
fprintf(stderr, "\n\n" );
|
||||
}
|
||||
|
||||
if (commandsfilename == NULL && f_usestdin == 0) {
|
||||
/* Must specify a message list */
|
||||
returnerr(stderr, "No mail message list specified (use <-s | -u commandsfilename>)\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
if (gt_testtime == 0) { /* NO TEST TIME */
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
if (gn_numprocs > MAXPROCSPERNODE || gn_numprocs < 1) {
|
||||
returnerr(stderr, "Number of clients must be between 1 and %d\n", MAXPROCSPERNODE);
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
crank_limits();
|
||||
|
||||
if (!gs_dateStamp[0]) {
|
||||
time(¤tTime);
|
||||
tmptm = localtime(¤tTime);
|
||||
strftime(gs_dateStamp, DATESTAMP_LEN, "%Y%m%d%H%M%S", tmptm);
|
||||
}
|
||||
|
||||
initializeCommands(commandsfilename); /* read command block */
|
||||
|
||||
gt_startedtime = time(0L);
|
||||
gt_shutdowntime = gt_startedtime + gt_testtime; /* start clean shutdown */
|
||||
gt_stopinterval = MAX ((ramptime/EXIT_FASTEST), 1); /* signal period */
|
||||
/* this is when the master gives up on the children */
|
||||
gt_aborttime = gt_shutdowntime + gt_stopinterval*2*EXIT_FASTEST;
|
||||
|
||||
|
||||
if ((pccxs = (pccx_t)mycalloc(sizeof(ccx_t) * gn_numprocs)) == NULL) {
|
||||
errexit(stderr, "error mycalloc() pccxs\n");
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "preparing serversock\n");
|
||||
|
||||
if ((serversock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
errexit(stderr, "socket() error: %s\n", neterrstr());
|
||||
}
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
/*saddr.sin_addr.S_ADDR = htonl(INADDR_ANY);*/
|
||||
saddr.sin_addr.S_ADDR = inet_addr("127.0.0.1");
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = 0;
|
||||
|
||||
if (bind(serversock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
|
||||
NETCLOSE(serversock);
|
||||
errexit(stderr, "bind() error: %s\n", neterrstr());
|
||||
}
|
||||
|
||||
if (listen(serversock, 512) == -1) {
|
||||
NETCLOSE(serversock);
|
||||
errexit(stderr, "listen() error: %s\n", neterrstr());
|
||||
}
|
||||
|
||||
addr_len = sizeof(saddr);
|
||||
if (getsockname(serversock, (struct sockaddr *)&saddr, &addr_len) == -1) {
|
||||
NETCLOSE(serversock);
|
||||
errexit(stderr, "getsockname() error: %s\n", neterrstr());
|
||||
}
|
||||
|
||||
listenport = saddr.sin_port;
|
||||
|
||||
D_PRINTF(stderr, "listening on [%s:%d]\n",
|
||||
safe_inet_ntoa(saddr.sin_addr, ntoabuf), ntohs(listenport));
|
||||
|
||||
setup_signal_handlers (); /* trap signals */
|
||||
|
||||
for(ii = 0; ii < gn_numprocs; ++ii) {
|
||||
D_PRINTF(stderr, "parent: forking client %d\n", ii);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (_beginthread(launchChild, NT_STACKSIZE, (void *)ii) == -1) {
|
||||
errexit(stderr, "_beginthread failed: %d", GetLastError());
|
||||
}
|
||||
#else
|
||||
#ifdef DIRECT_OUT /* for Unix, only if debugging */
|
||||
if (1 == gn_numprocs) {
|
||||
fprintf (stderr, "Single process, NOT forking.\n");
|
||||
launchChild (0); /* DEBUG */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
switch(pid=fork()) {
|
||||
case 0: /* CHILD */
|
||||
launchChild((void *)ii);
|
||||
exit(ii);
|
||||
break;
|
||||
case -1: /* ERROR */
|
||||
fprintf(stderr, "parent: error forking child %d, errno=%d: %s\n", ii, errno, strerror(errno));
|
||||
errexit(stderr, "Error forking child processes\n");
|
||||
exit(1);
|
||||
default: /* PARENT */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
pccxs[ii].pid = pid;
|
||||
|
||||
D_PRINTF(stderr, "parent: Accepting child %d pid=%d\n", ii, pid);
|
||||
/* Maybe fork everything before accepting */
|
||||
addr_len = sizeof(caddr);
|
||||
/* If the the child dies immediately, we hang here */
|
||||
if ((ret = accept(serversock, (struct sockaddr *)&caddr, &addr_len)) == -1) {
|
||||
errexit(stderr, "accept() error: %s\n", neterrstr());
|
||||
}
|
||||
D_PRINTF(stderr, "parent: child %d using socket %d\n", ii, ret);
|
||||
pccxs[ii].socket = ret;
|
||||
}
|
||||
|
||||
readwriteChildren(pccxs);
|
||||
|
||||
D_PRINTF(stderr, "done polling, now just wait\n");
|
||||
|
||||
waitChildren();
|
||||
|
||||
returnerr(stderr, "Master process done.\n");
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
return 0;
|
||||
} /* end main() */
|
||||
|
|
@ -1,425 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
* Mike Blakely
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
/* pop3.c: POP3 protocol test */
|
||||
|
||||
#include "bench.h"
|
||||
#include "pish.h"
|
||||
|
||||
typedef struct _doPOP3_state {
|
||||
int numMsgs; /* messages in folder */
|
||||
int totalMsgLength; /* total msg length */
|
||||
int msgCounter; /* count in download */
|
||||
} doPOP3_state_t;
|
||||
|
||||
/* POP3 flags definitions */
|
||||
#define leaveMailOnServer 0x01
|
||||
|
||||
static void doPop3Exit (ptcx_t ptcx, doPOP3_state_t *me);
|
||||
|
||||
|
||||
static int
|
||||
PopParseNameValue (pmail_command_t cmd,
|
||||
char *name,
|
||||
char *tok)
|
||||
{
|
||||
pish_command_t *pish = (pish_command_t *)cmd->data;
|
||||
|
||||
/* find a home for the attr/value */
|
||||
if (pishParseNameValue(cmd, name, tok) == 0)
|
||||
; /* done */
|
||||
else if (strcmp(name, "leavemailonserver") == 0)
|
||||
if (atoi(tok) > 0) {
|
||||
pish->flags |= leaveMailOnServer;
|
||||
} else {
|
||||
pish->flags &= ~leaveMailOnServer;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set defaults in command structure
|
||||
*/
|
||||
int
|
||||
Pop3ParseStart (pmail_command_t cmd,
|
||||
char *line,
|
||||
param_list_t *defparm)
|
||||
{
|
||||
param_list_t *pp;
|
||||
pish_command_t *pish = (pish_command_t *)mycalloc
|
||||
(sizeof (pish_command_t));
|
||||
cmd->data = pish;
|
||||
|
||||
cmd->numLoops = 9999; /* default 9999 downloads */
|
||||
pish->hostInfo.portNum = POP3_PORT; /* default port */
|
||||
|
||||
D_PRINTF(stderr, "Pop3 Assign defaults\n");
|
||||
/* Fill in defaults first, ignore defaults we dont use */
|
||||
for (pp = defparm; pp; pp = pp->next) {
|
||||
(void)PopParseNameValue (cmd, pp->name, pp->value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in command structure from a list of lines
|
||||
*/
|
||||
int
|
||||
Pop3ParseEnd (pmail_command_t cmd,
|
||||
string_list_t *section,
|
||||
param_list_t *defparm)
|
||||
{
|
||||
string_list_t *sp;
|
||||
pish_command_t *pish = (pish_command_t *)cmd->data;
|
||||
|
||||
/* Now parse section lines */
|
||||
D_PRINTF(stderr, "Pop3 Assign section lines\n");
|
||||
/* skip first and last */
|
||||
for (sp = section->next; sp->next; sp = sp->next) {
|
||||
char *name = sp->value;
|
||||
char *tok = name + strcspn(name, " \t=");
|
||||
*tok++ = 0; /* split name off */
|
||||
tok += strspn(tok, " \t=");
|
||||
|
||||
string_tolower(name);
|
||||
tok = string_unquote(tok);
|
||||
|
||||
if (PopParseNameValue (cmd, name, tok) < 0) {
|
||||
/* not a known attr */
|
||||
D_PRINTF(stderr,"unknown attribute '%s' '%s'\n", name, tok);
|
||||
returnerr(stderr,"unknown attribute '%s' '%s'\n", name, tok);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for some of the required command attrs */
|
||||
if (!pish->hostInfo.hostName) {
|
||||
D_PRINTF(stderr,"missing server for command");
|
||||
return returnerr(stderr,"missing server for command\n");
|
||||
}
|
||||
|
||||
if (!pish->loginFormat) {
|
||||
D_PRINTF(stderr,"missing loginFormat for command");
|
||||
return returnerr(stderr,"missing loginFormat for command\n");
|
||||
}
|
||||
|
||||
if (!pish->passwdFormat) {
|
||||
D_PRINTF(stderr,"missing passwdFormat for command");
|
||||
return returnerr(stderr,"missing passwdFormat for command\n");
|
||||
}
|
||||
|
||||
/* see if we can resolve the mailserver addr */
|
||||
if (resolve_addrs(pish->hostInfo.hostName, "tcp",
|
||||
&(pish->hostInfo.host_phe),
|
||||
&(pish->hostInfo.host_ppe),
|
||||
&(pish->hostInfo.host_addr),
|
||||
&(pish->hostInfo.host_type))) {
|
||||
return returnerr (stderr, "Error resolving hostname '%s'\n",
|
||||
pish->hostInfo.hostName);
|
||||
} else {
|
||||
pish->hostInfo.resolved = 1; /* mark the hostInfo resolved */
|
||||
}
|
||||
|
||||
rangeSetFirstCount (&pish->loginRange, pish->loginRange.first,
|
||||
pish->loginRange.span, pish->loginRange.sequential);
|
||||
rangeSetFirstCount (&pish->domainRange, pish->domainRange.first,
|
||||
pish->domainRange.span, pish->domainRange.sequential);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
doPopCommandResponse(ptcx_t ptcx, SOCKET sock, char *command, char *response, int resplen)
|
||||
{
|
||||
int rc;
|
||||
|
||||
T_PRINTF(ptcx->logfile, command, strlen (command), "POP3 SendCommand");
|
||||
rc = doCommandResponse(ptcx, sock, command, response, resplen);
|
||||
if (rc == -1)
|
||||
return rc;
|
||||
T_PRINTF(ptcx->logfile, response, strlen(response),
|
||||
"POP3 ReadResponse"); /* telemetry log. should be lower level */
|
||||
/* D_PRINTF(stderr, "POP command=[%s] response=[%s]\n", command, response); */
|
||||
if (strncmp(response, "+OK", 3) != 0) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
trimEndWhite (command);
|
||||
trimEndWhite (response);
|
||||
returnerr(debugfile,"POP3 error command=[%s] response=[%s]\n",
|
||||
command, response);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
popLogin(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, SOCKET sock)
|
||||
{
|
||||
char command[MAX_COMMAND_LEN];
|
||||
char respBuffer[MAX_RESPONSE_LEN];
|
||||
char mailUser[MAX_MAILADDR_LEN];
|
||||
char userPasswd[MAX_MAILADDR_LEN];
|
||||
unsigned long loginNum;
|
||||
unsigned long domainNum;
|
||||
int rc;
|
||||
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
|
||||
pish_command_t *pish = (pish_command_t *)cmd->data;
|
||||
|
||||
/* generate a random username and domainname(with a mailbox on the server) */
|
||||
domainNum = rangeNext (&stats->domainRange, stats->lastDomain);
|
||||
stats->lastDomain = domainNum;
|
||||
loginNum = rangeNext (&stats->loginRange, stats->lastLogin);
|
||||
stats->lastLogin = loginNum;
|
||||
|
||||
sprintf(mailUser, pish->loginFormat, loginNum, domainNum);
|
||||
D_PRINTF(debugfile,"mailUser=%s\n", mailUser);
|
||||
sprintf(command, "USER %s%s", mailUser, CRLF);
|
||||
|
||||
event_start(ptcx, &stats->cmd);
|
||||
rc = doPopCommandResponse(ptcx, sock, command, respBuffer, sizeof(respBuffer));
|
||||
event_stop(ptcx, &stats->cmd);
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->login.errs++;
|
||||
/* error already displayed */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send Password */
|
||||
sprintf(userPasswd, pish->passwdFormat, loginNum);
|
||||
sprintf(command, "PASS %s%s", userPasswd, CRLF);
|
||||
|
||||
event_start(ptcx, &stats->login);
|
||||
rc = doPopCommandResponse(ptcx, sock, command, respBuffer, sizeof(respBuffer));
|
||||
event_stop(ptcx, &stats->login);
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->login.errs++;
|
||||
returnerr(debugfile,"POP3 cannot login user=%s pass=%s\n",
|
||||
mailUser, userPasswd);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
doPop3Start(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
|
||||
{
|
||||
doPOP3_state_t *me = (doPOP3_state_t *)mycalloc (sizeof (doPOP3_state_t));
|
||||
char respBuffer[MAX_RESPONSE_LEN];
|
||||
int rc;
|
||||
int numBytes;
|
||||
char command[MAX_COMMAND_LEN];
|
||||
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
|
||||
pish_command_t *pish = (pish_command_t *)cmd->data;
|
||||
|
||||
if (!me) return NULL;
|
||||
|
||||
me->numMsgs = 0;
|
||||
me->totalMsgLength = 0;
|
||||
me->msgCounter = 0;
|
||||
|
||||
event_start(ptcx, &stats->connect);
|
||||
ptcx->sock = connectSocket(ptcx, &pish->hostInfo, "tcp");
|
||||
event_stop(ptcx, &stats->connect);
|
||||
if (BADSOCKET(ptcx->sock)) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->connect.errs++;
|
||||
returnerr(debugfile, "POP3 Couldn't connect to %s: %s\n",
|
||||
pish->hostInfo.hostName, neterrstr());
|
||||
}
|
||||
myfree (me);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gf_abortive_close) {
|
||||
if (set_abortive_close(ptcx->sock) != 0) {
|
||||
returnerr (debugfile, "POP3: WARNING: Could not set abortive close\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* READ connect response from server */
|
||||
event_start(ptcx, &stats->banner);
|
||||
numBytes = readResponse(ptcx, ptcx->sock, respBuffer, sizeof(respBuffer));
|
||||
event_stop(ptcx, &stats->banner);
|
||||
if (numBytes <= 0) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->banner.errs++;
|
||||
returnerr(debugfile,"POP3 Error reading banner: %s\n",
|
||||
neterrstr());
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* LOGIN
|
||||
*/
|
||||
|
||||
rc = popLogin(ptcx, cmd, ptimer, ptcx->sock);
|
||||
if (rc != 0) {
|
||||
doPop3Exit (ptcx, me);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* send a STAT */
|
||||
sprintf(command, "STAT%s", CRLF);
|
||||
event_start(ptcx, &stats->cmd);
|
||||
rc = doPopCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
|
||||
event_stop(ptcx, &stats->cmd);
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->cmd.errs++;
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* parse number of msgs out of buffer */
|
||||
if (!sscanf(respBuffer, "+OK %d %d", &me->numMsgs, &me->totalMsgLength)) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->cmd.errs++;
|
||||
returnerr(debugfile,"POP3 Error parsing STAT response, %s: %s\n",
|
||||
respBuffer, neterrstr());
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D_PRINTF(debugfile,"STAT shows %d msgs of %d total bytes\n",
|
||||
me->numMsgs, me->totalMsgLength);
|
||||
return me;
|
||||
}
|
||||
|
||||
int
|
||||
doPop3Loop(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
|
||||
{
|
||||
doPOP3_state_t *me = (doPOP3_state_t *)mystate;
|
||||
char command[MAX_COMMAND_LEN];
|
||||
char respBuffer[MAX_RESPONSE_LEN];
|
||||
int rc, numBytes;
|
||||
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
|
||||
pish_command_t *pish = (pish_command_t *)cmd->data;
|
||||
|
||||
if (me->msgCounter >= me->numMsgs) return -1; /* done, close */
|
||||
|
||||
/* retr the msgs */
|
||||
/* send the RETR command */
|
||||
sprintf(command, "RETR %d%s", ++me->msgCounter, CRLF);
|
||||
event_start(ptcx, &stats->msgread);
|
||||
rc = sendCommand(ptcx, ptcx->sock, command);
|
||||
if (rc == -1) {
|
||||
event_stop(ptcx, &stats->msgread);
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->msgread.errs++;
|
||||
returnerr(debugfile,"POP3 Error sending RETR %d command: %s\n",
|
||||
me->msgCounter, neterrstr());
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read msg */
|
||||
numBytes = retrMsg(ptcx, NULL, 0 , ptcx->sock);
|
||||
event_stop(ptcx, &stats->msgread);
|
||||
|
||||
if (numBytes <= 0) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->msgread.errs++;
|
||||
returnerr(debugfile,"POP3 Error retrieving msg %d: %s\n",
|
||||
me->msgCounter, neterrstr());
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if we're not told to leave mail on server, delete the message */
|
||||
if (!(pish->flags & leaveMailOnServer)) {
|
||||
/* send the DELE command */
|
||||
sprintf(command, "DELE %d%s", me->msgCounter, CRLF);
|
||||
event_start(ptcx, &stats->cmd);
|
||||
rc = doPopCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
|
||||
event_stop(ptcx, &stats->cmd);
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->cmd.errs++;
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
doPop3End(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
|
||||
{
|
||||
doPOP3_state_t *me = (doPOP3_state_t *)mystate;
|
||||
char command[MAX_COMMAND_LEN];
|
||||
char respBuffer[MAX_RESPONSE_LEN];
|
||||
int rc;
|
||||
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
|
||||
|
||||
if (BADSOCKET(ptcx->sock)) return; /* closed by previous error */
|
||||
|
||||
/* send QUIT */
|
||||
sprintf(command, "QUIT%s", CRLF);
|
||||
event_start(ptcx, &stats->logout);
|
||||
rc = doPopCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
|
||||
event_stop(ptcx, &stats->logout);
|
||||
if (rc == -1) {
|
||||
if (gf_timeexpired < EXIT_FAST) {
|
||||
stats->logout.errs++; /* counted twice? */
|
||||
}
|
||||
}
|
||||
doPop3Exit (ptcx, me);
|
||||
}
|
||||
|
||||
void
|
||||
doPop3Exit (ptcx_t ptcx, doPOP3_state_t *me)
|
||||
{
|
||||
if (!BADSOCKET(ptcx->sock))
|
||||
NETCLOSE(ptcx->sock);
|
||||
ptcx->sock = BADSOCKET_VALUE;
|
||||
|
||||
myfree (me);
|
||||
}
|
1218
mstone/src/smtp.c
1218
mstone/src/smtp.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,397 +0,0 @@
|
|||
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Mailstone utility,
|
||||
* released March 17, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Christian <robodan@netscape.com>
|
||||
* Marcel DePaolis <marcel@netcape.com>
|
||||
* Mike Blakely
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License Version 2 or later (the "GPL"), in
|
||||
* which case the provisions of the GPL are applicable instead of
|
||||
* those above. If you wish to allow use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice and
|
||||
* other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file
|
||||
* under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
#include "bench.h"
|
||||
|
||||
#ifdef USE_LRAND48_R /* also AIX (only when using threads)*/
|
||||
|
||||
struct drand48_data drand48data;
|
||||
|
||||
/* should verify that the struct drand48_data can be shared between threads */
|
||||
void
|
||||
osf_srand48_r(unsigned int seed)
|
||||
{
|
||||
srand48_r(seed, &drand48data);
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
osf_lrand48_r(void)
|
||||
{
|
||||
long ret;
|
||||
|
||||
lrand48_r(&drand48data, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __OSF1__ */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* close socket library at exit() time */
|
||||
void sock_cleanup(void) {
|
||||
WSACleanup();
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* neither sleep or usleep re-start if interrupted */
|
||||
void
|
||||
MS_sleep(unsigned int secs)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep(secs * 1000);
|
||||
#else
|
||||
struct timeval sleeptime;
|
||||
|
||||
/*D_PRINTF(stderr, "MS_sleep(%d)\n", secs);*/
|
||||
|
||||
sleeptime.tv_sec = secs;
|
||||
sleeptime.tv_usec = 0;
|
||||
if (select( (int)NULL, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
|
||||
&sleeptime ) < 0) {
|
||||
D_PRINTF (stderr, "MS_sleep %lu returned early\n", secs);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MS_usleep(unsigned int microsecs)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep(microsecs / 1000);
|
||||
#else
|
||||
struct timeval sleeptime;
|
||||
|
||||
/*D_PRINTF(stderr, "MS_usleep(%d)\n", microsecs);*/
|
||||
|
||||
sleeptime.tv_sec = USECS_2_SECS(microsecs);
|
||||
sleeptime.tv_usec = microsecs % USECINSEC;
|
||||
if (select( (int)NULL, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
|
||||
&sleeptime ) < 0) {
|
||||
D_PRINTF (stderr, "MS_usleep %lu returned early\n", microsecs);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* strerror() */
|
||||
#ifndef HAVE_STRERROR
|
||||
/* strerror is not available on SunOS 4.1.3 and others */
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
|
||||
char *strerror(int errnum)
|
||||
{
|
||||
if (errnum<sys_nerr) {
|
||||
return(sys_errlist[errnum]);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* strerror() */
|
||||
|
||||
/* stub routines for NT */
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#include <process.h>
|
||||
|
||||
int getpid(void) {
|
||||
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
#include <sys/timeb.h> /* For prototype of "_ftime()" */
|
||||
/*
|
||||
* gettimeofday() -- gets the current time in elapsed seconds and
|
||||
* microsends since GMT Jan 1, 1970.
|
||||
*
|
||||
* ARGUMENTS: - Pointer to a timeval struct to return the time into
|
||||
*
|
||||
* RETURN CODES: - 0 on success
|
||||
* -1 on failure
|
||||
*/
|
||||
int gettimeofday(struct timeval *curTimeP)
|
||||
{
|
||||
struct _timeb localTime;
|
||||
|
||||
if (curTimeP == (struct timeval *) NULL) {
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the elapsed time since Jan 1, 1970 by first
|
||||
* obtaining the elapsed time from the system using the
|
||||
* _ftime(..) call and then convert to the "timeval"
|
||||
* equivalent.
|
||||
*/
|
||||
|
||||
_ftime(&localTime);
|
||||
|
||||
curTimeP->tv_sec = localTime.time;
|
||||
curTimeP->tv_usec = localTime.millitm * 1000;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
crank_limits(void)
|
||||
{}
|
||||
|
||||
void
|
||||
setup_signal_handlers(void)
|
||||
{}
|
||||
|
||||
int
|
||||
sysdep_thread_create(THREAD_ID *id, thread_fn_t tfn, void *arg)
|
||||
{
|
||||
if (_beginthread(tfn, NT_STACKSIZE, arg) == -1) {
|
||||
errexit(stderr, "_beginthread failed: %d", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysdep_thread_join(THREAD_ID id, int *pstatus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#define MAX_TRYFDS (64*1024)
|
||||
|
||||
void
|
||||
crank_limits(void)
|
||||
{
|
||||
struct rlimit rlim;
|
||||
int cur_lim;
|
||||
int rc;
|
||||
|
||||
#ifdef __OSF1__
|
||||
D_PRINTF(stderr, "attempting to enable support for up to 64k file descriptors\n");
|
||||
|
||||
rc = setsysinfo(SSI_FD_NEWMAX, NULL, 0, NULL, 1);
|
||||
if (rc == -1) {
|
||||
perror("setsysinfo()");
|
||||
}
|
||||
#endif /* __OSF1__ */
|
||||
|
||||
D_PRINTF(stderr, "attempting to increase our hard limit (up to %d)\n", MAX_TRYFDS);
|
||||
|
||||
rc = getrlimit(RLIMIT_NOFILE, &rlim);
|
||||
if (rc == -1) {
|
||||
returnerr(stderr, "getrlimit()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (cur_lim = rlim.rlim_max; cur_lim < MAX_TRYFDS; cur_lim += 1024) {
|
||||
rlim.rlim_max = cur_lim;
|
||||
|
||||
rc = setrlimit(RLIMIT_NOFILE, &rlim);
|
||||
if (rc == -1) {
|
||||
D_PRINTF (stderr, "setrlimit(RLIMIT_NOFILE, [rlim_max=%d]): errno=%d: %s\n",
|
||||
rlim.rlim_max, errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D_PRINTF(stderr, "attempting to increase our soft limit\n");
|
||||
|
||||
rc = getrlimit(RLIMIT_NOFILE, &rlim);
|
||||
if (rc == -1) {
|
||||
returnerr(stderr, "getrlimit()");
|
||||
exit(-1);
|
||||
}
|
||||
rlim.rlim_cur = rlim.rlim_max;
|
||||
|
||||
rc = setrlimit(RLIMIT_NOFILE, &rlim);
|
||||
if (rc == -1) {
|
||||
D_PRINTF (stderr, "setrlimit(RLIMIT_NOFILE, [rlim_cur=%d]): errno=%d: %s\n",
|
||||
rlim.rlim_cur, errno, strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
getrlimit(RLIMIT_NOFILE, &rlim);
|
||||
if (rlim.rlim_cur < 256) { /* show if lower than docs suggest */
|
||||
returnerr (stderr, "RLIMIT_NOFILE = %d. max processes/threads ~ %d\n",
|
||||
rlim.rlim_cur, rlim.rlim_cur-10);
|
||||
} else {
|
||||
D_PRINTF (stderr, "RLIMIT_NOFILE = %d. max processes/threads ~ %d\n",
|
||||
rlim.rlim_cur, rlim.rlim_cur-10);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nullHandler(int sig)
|
||||
{
|
||||
/* Dont do anything, (trap SIGPIPE) */
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
alarmHandler(int sig)
|
||||
{
|
||||
/* Dont do anything, mainly break system calls */
|
||||
if (gf_timeexpired < EXIT_SOON) gf_timeexpired = EXIT_SOON;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
hupHandler(int sig)
|
||||
{
|
||||
if (gf_timeexpired < EXIT_SOON) { /* first time, go to clean stop */
|
||||
beginShutdown ();
|
||||
} else if (gf_timeexpired < EXIT_FAST) { /* second time, faster */
|
||||
gf_timeexpired = EXIT_FAST;
|
||||
} else if (gf_timeexpired < EXIT_FASTEST) { /* second time, fastest */
|
||||
gf_timeexpired = EXIT_FASTEST;
|
||||
} else { /* third time, exit */
|
||||
exit (sig);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* not used */
|
||||
/* Received a signal that a child process has exited */
|
||||
void
|
||||
childHandler(int sig)
|
||||
{
|
||||
int status;
|
||||
|
||||
/*D_PRINTF(stderr, "A child process has exited\n" );*/
|
||||
while (wait3(&status, WNOHANG, (struct rusage *)0) > 0) {
|
||||
/* do nothing */
|
||||
/*D_PRINTF(stderr, "wait3() says %d died\n", status);;*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
setup_signal_handlers(void)
|
||||
{
|
||||
/* We will loop until the alarm goes off (should abort system calls). */
|
||||
#ifdef __LINUX__
|
||||
{ /* setup signal handler */
|
||||
struct sigaction sig;
|
||||
sig.sa_flags = 0;
|
||||
sig.sa_restorer = 0;
|
||||
sigemptyset (&sig.sa_mask);
|
||||
|
||||
sig.sa_handler = alarmHandler;
|
||||
sigaction (SIGALRM, &sig, NULL);
|
||||
|
||||
sig.sa_handler = hupHandler;
|
||||
sigaction (SIGHUP, &sig, NULL);
|
||||
sigaction (SIGTERM, &sig, NULL);
|
||||
|
||||
sig.sa_handler = nullHandler;
|
||||
sigaction (SIGPIPE, &sig, NULL);
|
||||
|
||||
}
|
||||
#else
|
||||
sigset(SIGALRM, alarmHandler);
|
||||
sigset(SIGHUP, hupHandler);
|
||||
sigset(SIGTERM, hupHandler);
|
||||
sigset(SIGPIPE, nullHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
sysdep_thread_create(THREAD_ID *id, thread_fn_t tfn, void *arg)
|
||||
{
|
||||
#ifdef USE_PTHREADS
|
||||
int ret;
|
||||
pthread_attr_t attr;
|
||||
|
||||
if ((ret=pthread_attr_init(&attr)) != 0) {
|
||||
returnerr(stderr, "pthread_attr_init() ret=%d errno=%d: %s\n",
|
||||
ret, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0 /* the default thread attributes */
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);
|
||||
pthread_attr_setstackaddr(&attr, NULL); /* allocated by system */
|
||||
pthread_attr_setstacksize(&attr, NULL); /* 1 MB */
|
||||
pthread_attr_setschedparam(&attr, _PARENT_); /* priority of parent */
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_OTHER); /* determined by system */
|
||||
/* also have SCHED_FIFO and SCHED_RR */
|
||||
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
||||
#endif
|
||||
#ifdef __AIX__
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
|
||||
#else
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
#endif
|
||||
|
||||
#ifdef THREADS_SCOPE_SYSTEM
|
||||
/* bound threads, one thread per LWP */
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||
#endif
|
||||
|
||||
if ((ret=pthread_create(id, &attr, tfn, arg)) != 0) {
|
||||
returnerr(stderr, "pthread_create() failed ret=%d errno=%d: %s\n",
|
||||
ret, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if ((ret=pthread_attr_destroy(&attr)) != 0) {
|
||||
returnerr(stderr, "pthread_attr_destroy() ret=%d errno=%d: %s\n",
|
||||
ret, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysdep_thread_join(THREAD_ID id, int *pstatus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
*pstatus = 0;
|
||||
if ((ret = pthread_join(id, (void **)pstatus)) == 0)
|
||||
break;
|
||||
D_PRINTF(stderr, "pthread_join(%d) error ret=%d status=%d: errno=%d: %s\n",
|
||||
id, ret, *pstatus, errno, strerror(errno));
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
1000
mstone/src/wmap.c
1000
mstone/src/wmap.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче