Pivotal GemFire Function Service and Scala

Yes Pivotal GemFire functions can be written in Scala. Pivotal GemFire Functions are described here
I am not going to write all the details about function Service. Since Scala is inter operable with Java, One can easily write Pivotal Gemfire functions in Scala and they will work as you wrote the functions in Java

Following is the Scala implementation of the MultiGetFunction taken from Function Service.

Step 1 : Write a Java wrapper around Gemfire Function Interface like below

package pivotal.scala.wrapper.functions;

import com.gemstone.gemfire.cache.execute.FunctionAdapter;
import com.gemstone.gemfire.cache.execute.FunctionContext;

public abstract class ScalaFunctionAdapter extends FunctionAdapter {    
  @Override
  public void execute(FunctionContext arg0) {
    executeScalaWrapper(arg0);
  }
  @Override
  public String getId() {
    return getIdScalaWrapper();
  }
  public abstract String getIdScalaWrapper();    
  public abstract void executeScalaWrapper(FunctionContext arg0);    
}

Step 2: Implement this interface in Scala , for example like below

package scala.gemfire.quickstart

import scala.collection.JavaConversions._
import com.gemstone.gemfire.cache.execute.FunctionAdapter
import com.gemstone.gemfire.cache.CacheFactory
import com.gemstone.gemfire.cache.execute.RegionFunctionContext
import com.gemstone.gemfire.cache.Region
import com.gemstone.gemfire.cache.Declarable
import com.gemstone.gemfire.cache.execute.FunctionContext
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper
import pivotal.scala.wrapper.functions.ScalaFunctionAdapter

class MultiGetFunction extends ScalaFunctionAdapter {

  def getIdScalaWrapper: String = this.getClass.getName

  def executeScalaWrapper(fc: FunctionContext): Unit = {
    fc match {
      case frc: RegionFunctionContext => {
        val context = frc.asInstanceOf[RegionFunctionContext]
        val keys = context.getFilter()
        var keysTillSecondLast = new scala.collection.mutable.HashSet[Any]()
        keysTillSecondLast.addAll(keys.take(keys.size - 1))
        keysTillSecondLast.foreach { key =>
          context.getResultSender().
            sendResult(PartitionRegionHelper.
              getLocalDataForContext(context).get(key));
        }
        context.getResultSender().
          lastResult(PartitionRegionHelper.
            getLocalDataForContext(context).get(keys.last));
      }
      case _ => {
        fc.getResultSender().
          lastResult(Runtime.getRuntime().freeMemory() / (1024 * 1024));
      }
    }
  } 
}

Step 3 : Build code using sbt ( Java Wrapper + Scala Implementation of the functionAdapter)
Step 4: Use the built jar as a Function Execution code in java project.
Step 5: Note to add scala-library.jar in the classpath, sbt assembly combine all the deps but I have not tried that yet.

Using GemfireXD with Clojure

Clojure is a dynamic programming language that targets the Java Virtual Machine See here for further details. I like the language for many reasons and some of them are Full access to Java’s rich, mature API, Clojure is a Lisp, so all of the advantages that apply to Lisps apply to Clojure, Because “code is data”, you can do really neat things with macros and many more see here for more of why Clojure is awesome language to learn.

GemFire XD®, built on over a decade of innovation in real-time distributed systems, integrates with Pivotal HD and HAWQ to provide the industry’s first platform for creating closed loop analytics solutions. for more details about GemFire XD® see here.

In this post I am going to show how to access GemFire XD® using Clojure.

Java uses an API called JDBC to access databases, each vendor provides drivers to access their database systems, GemFire XD® uses JDBC driver for access. Download the jar file and place it on your classpath before starting Clojure REPL or Clojure Script

Clojure java.jdbc contains an interface to SQL databases via JDBC, first import the SQL interface

( ns clojure.gemfireXD.jdbc
  (:require [clojure.java.jdbc :as JDBC]))

Define the connection Parameters

def db-spec {:classname "com.vmware.sqlfire.jdbc.ClientDriver"
                :subprotocol "sqlfire"
                :subname "//localhost:1527/"})

You can either use DSL by the java.jdbc package or you can just simple execute any queries you want like below

(defn using-simple-queries
  []  
  (JDBC/db-do-commands db-spec true 
         "create table customer (
        c_w_id         integer        not null,
        c_d_id         integer        not null,
        c_id           integer        not null,
        c_discount     decimal(4,4), c_credit       char(2),
        c_last         varchar(16), c_first        varchar(16),
        c_credit_lim   decimal(12,2), c_balance      decimal(12,2),
        c_ytd_payment  float, c_payment_cnt  integer,
        c_delivery_cnt integer, c_street_1     varchar(20),
        c_street_2     varchar(20), c_city         varchar(20),
        c_state        char(2), c_zip          char(9),
        c_phone        char(16), c_since        timestamp,
        c_middle       char(2), c_data         varchar(500)) partition by (c_w_id) redundancy 1")
  (JDBC/db-do-commands db-spec true 
          "create table new_order ( no_w_id  integer   not null,
        no_d_id  integer   not null,no_o_id  integer   not null) 
        partition by (no_w_id) colocate with (customer) redundancy 1")

  (JDBC/db-do-commands db-spec true "alter table customer add constraint pk_customer 
        primary key (c_w_id, c_d_id, c_id)")

  (JDBC/db-do-commands db-spec true "create index ndx_customer_name 
        on customer (c_w_id, c_d_id, c_last)")

  (JDBC/db-do-commands db-spec true "alter table new_order add constraint pk_new_order
        primary key (no_w_id, no_d_id, no_o_id)")

  (JDBC/db-do-commands db-spec true, "create index ndx_neworder_w_id_d_id
        on new_order (no_w_id, no_d_id)")

  (JDBC/db-do-commands db-spec true "create index ndx_neworder_w_id_d_id_o_id
        on new_order (no_w_id, no_d_id, no_o_id)")
)

Creating a table using java.jdbc of Clojure DSL.

(defn create-table-customer
  [db-spec]
  (JDBC/db-do-commands
    db-spec ( JDBC/create-table-ddl
              :customer
              [:c_w_id         :integer    "not null"]
              [:c_d_id         :integer    "not null"]
              [:c_id           :integer    "not null"]
              [:c_discount     :decimal    "(4,4)"]
              [:c_credit       :char       "(2)"]
              [:c_last         :varchar    "(16)"]
              [:c_first        :varchar    "(16)"]
              [:c_credit_lim   :decimal    "(12,2)"]
              [:c_balance      :decimal    "(12,2)"]
              [:c_ytd_payment  :float]
              [:c_payment_cnt  :integer]
              [:c_delivery_cnt :integer] 
              [:c_street_1     :varchar    "(20)"]
              [:c_street_2     :varchar    "(20)"] 
              [:c_city         :varchar    "(20)"]
              [:c_state        :char       "(2)"]
              [:c_zip          :char       "(9)"]
              [:c_phone        :char       "(16)"] 
              [:c_since        :timestamp]
              [:c_middle       :char       "(2)"]
              [:c_data         :varchar    "(500)"]
              :table-spec "partition by (c_w_id) redundancy 1")))

  (defn create-table-new-order
    [db-spec]
    (JDBC/db-do-commands 
      db-spec
      (JDBC/create-table-ddl
        :new_order
        [:no_w_id  :integer   "not null"]
        [:no_d_id  :integer   "not null"]
        [:no_o_id  :integer   "not null"]
        :table-spec "partition by (no_w_id) colocate with (customer) redundancy 1")))  

Here is the complete working code

( try
  (JDBC/db-do-commands db-spec (JDBC/drop-table-ddl :new_order))
  (JDBC/db-do-commands db-spec (JDBC/drop-table-ddl :customer))
  (catch Exception _ ;;ignore 
  ))
(create-table-customer db-spec)
(create-table-new-order db-spec)

(JDBC/db-do-commands db-spec true "alter table customer add constraint pk_customer primary key (c_w_id, c_d_id, c_id)")

(JDBC/db-do-commands db-spec true "create index ndx_customer_name on customer (c_w_id, c_d_id, c_last)")

(JDBC/db-do-commands db-spec true "alter table new_order add constraint pk_new_order primary key (no_w_id, no_d_id, no_o_id)")

(JDBC/db-do-commands db-spec true "create index ndx_neworder_w_id_d_id on new_order (no_w_id, no_d_id)")

(JDBC/db-do-commands db-spec true "create index ndx_neworder_w_id_d_id_o_id on new_order (no_w_id, no_d_id, no_o_id)")

(JDBC/db-do-prepared db-spec true "insert into new_order values (?, ?, ?)" [1 1 1][2 2 2][3 3 3][4 4 4][5 5 5][6 6 6][7 7 7][8 8 8][9 9 9][10 10 10])

(println (JDBC/query db-spec ["SELECT * FROM new_order"] :result-set-fn count))

and there you go start using GemFire XD® using Clojure. Clojure Java.jdbc also provides api for accesing Database Metadata.
One can also use Clojure Connecton pooling Clojure JDBC pool

Building R on Ubuntu

Today morning I wanted to do experiments with RJDBC . To my surprise Ubuntu 12.04 does not have latest version of R
Following are the steps I have followed to build R on Ubuntu.

  • Install the required dependencies.
  • sudo apt-get install gcc g++ gfortran libreadline-dev libx11-dev xorg-dev
    
  • Download the source.
  • svn checkout https://svn.r-project.org/R/trunk/ r-devel
    
  • Sync the required modules.
  • cd r-devel/
    apt-get install rsync
    sudo apt-get install rsync
    ./tools/rsync-recommended
    

    If you are behind firewall, setup RSYNC_PROXY.

  • Configure and Make.
  • JAVA_HOME=<your java home> ./configure --prefix <where you want to install the binaries>
    make
    
  • Install.
  • make install
    

    Making Apache Thrift Selector Server Non-blocking

    Recently I am doing lot of experiments with Apache Thrift. Interesting piece of software framework  for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.

    Documentation seems to very limited. I was trying to use TThreadedSelectorServer 

    Typical usage of TThreadedSelectorServer I found is as below

    TNonblockingServerTransport trans = new TNonblockingServerSocket(port);
    TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(trans);
    args.transportFactory(new TFramedTransport.Factory());
    args.protocolFactory(new TBinaryProtocol.Factory());
    args.processor(your processor);
    args.selectorThreads(4);
    args.workerThreads(32);
    TServer server = new TThreadedSelectorServer(args);
    server.serve();
    

    But this serve is blocking call and you cannot use it in your already available server. Or I do not know any other way to make it embedded.

    Here is my solution to make it work .

    Create a new class child of TThreadedSelectorServer and implement serve and stop as below and you are good to go.

    public class MyTThreadedSelectorServer extends TThreadedSelectorServer {
    
      public MyTThreadedSelectorServer(Args args) {
        super(args);
      }
    
      public void serve() {
        if (!startThreads()) {
          return;
        }
        // start listening, or exit
        if (!startListening()) {
          return;
        }
        setServing(true);
      }
    
      public void stop() {
        setServing(false);
        super.stop();
      }
    
    }
    

    Building Thirift on Ubuntu behind firewall

    I was trying to build thrift on ubuntu and hit some issues, specially because my machine was behind the firewall. I am going to put down the steps to build thrift.
    You need some more packages on your box and boost.

    • Dowload Boost
    • Building boost instruction are given on there site, but you can use following command to build the boost locally
    • ./bootstrap.sh
      ./bootstrap.sh --prefix=/usr/local/boost_1_46_1
      ./bjam install
      
    • External packages required to build thrift can be done using following command
    • sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev
      
    • Go to thrift directory where you have un-archived the source code
    • Build thrift using following command providing boost directory and JAVAC location
    • ./configure --with-boost=/usr/local/boost_1_46_1 JAVAC=/home/avinash/export/where/jdk/1.6.0_26/x86.linux/bin/javac
      
    • Upon completing successfull configuration, run make command
    • make
      

      If you are behind firewall you might hit error regarding downloading jars from maven repository.
      Maven tries to auto download the dependencies if they are not available within your local repository,
      since maven did not know of your proxy it was unable to download them and failed. Adding the
      proxy config to your maven settings.xml should resolve your problem when you box is behind firewall

    • Open your build.xml from your java directory
    • /home/avinash/work/thrift-0.9.0/lib/java/build.xml
      
    • Look for target mvn.ant.tasks.download
    • Add following proxy settings to your file
      <setproxy proxyhost="your proxy server name" proxyport="port number"/>
      
    • So new target looks like below
    •  <target name="mvn.ant.tasks.download" depends="setup.init,mvn.ant.tasks.check,proxy" unless="mvn.ant.tasks.found">
          <setproxy proxyhost="proxy.com" proxyport="1234"/>
          <get src="${mvn.ant.task.url}/${mvn.ant.task.jar}" dest="${build.tools.dir}/${mvn.ant.task.jar}" usetimestamp="true"/>
        </target>
      

      This will solve your initial download issue but mvn.init target still give you issue while downloading maven depencies

    • If you already do not have settings.xml
    • Create it in your home folder under .m2 directory
    • Add following lines in the settings.xml file
    • <settings>
        <proxies>
         <proxy>
            <active>true</active>
            <protocol>http</protocol>
            <host>PROXY-SERVER-NAME</host>
            <port>PROXY-SERVER-PORT</port>
            <username>proxyuser</username>
            <password>somepassword</password>
            <nonProxyHosts>www.google.com|*.somewhere.com</nonProxyHosts>
          </proxy>
        </proxies>
      </settings>
      
    • and run make again.

    BEAUTIFUL STRINGS

    PROBLEM STATEMENT

    When John was a little kid he didn’t have much to do. There was no internet, no Facebook, and no programs to hack on. So he did the only thing he could… he evaluated the beauty of strings in a quest to discover the most beautiful string in the world.

    Given a string S, little Johnny defined the beauty of the string as the sum of the beauty of the letters in it.

    The beauty of each letter is an integer between 1 and 26, inclusive, and no two letters have the same beauty. Johnny doesn’t care about whether letters are
    uppercase or lowercase, so that doesn’t affect the beauty of a letter. (Uppercase ‘F’ is exactly as beautiful as lowercase ‘f’, for example.)

    You’re a student writing a report on the youth of this famous hacker. You found the string that Johnny considered most beautiful. What is the maximum possible beauty of this string?

    INPUT

    The input file consists of a single integer m followed by m lines.
    OUTPUT

    Your output should consist of, for each test case, a line containing the string “Case #x: y” where x is the case number (with 1 being the first case in the
    input file, 2 being the second, etc.) and y is the maximum beauty for that test case.

    CONSTRAINTS

    5 <= M <= 50
    2 <= length of S <= 500
    

    EXAMPLE INPUT

        5
        ABbCcc
        Good luck in the Facebook Hacker Cup this year!
        Ignore punctuation, please :)
        Sometimes test cases are hard to make up.
        So I just go consult Professor Dalves
    

    EXAMPLE OUTPUT

        Case #1: 152
        Case #2: 754
        Case #3: 491
        Case #4: 729
        Case #5: 646
    

    Solution:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm>
    #include <vector>
    
    struct InvalidChar
    {
        bool operator()(char c) const {
            return !isalpha((unsigned)c);
        }
    };
    
    int main( int argc, char **argv) 
    {
        if ( argc <= 1 ) {
            return 0;
        }
        std::ifstream input(argv[1]);
        if ( input.peek() == EOF ) {
            return 0;
        }
        // Read the number of test cases
        int M;
        input >> M ;
        // Read the first line and ignore it
        std::string line;
        std::getline (input,line);
        for ( int m = 0; m < M ; m++) {
            std::vector<int> occurences;
            occurences.resize(26);
            std::getline (input,line);
            std::transform(line.begin(), line.end(), line.begin(), ::tolower);
            line.erase(std::remove_if(line.begin(),line.end(),InvalidChar()), line.end());
            if ( !line.empty()) {
                for ( int i = 0; i < (int)line.size(); i++) {
                    occurences[line[i] - 'a']++;
                }
            }
            occurences.erase(std::remove(occurences.begin(), occurences.end(), 0), occurences.end());
            std::sort(occurences.begin(), occurences.end(), std::greater<int>());
            int multiply_factor = 26;
            int final_answer = 0;
            for ( std::vector<int>::iterator itr = occurences.begin(); itr != occurences.end(); ++itr) {
                final_answer += (*itr) * multiply_factor--;
            }
            std::cout << "Case #" << m + 1 << ":  " << final_answer << std::endl;
        }
        input.close();
        return 0;
    }
    

    Finding Memory leak in C++ Application on Windows

    Finding memory leaks can be very difficult job sometimes, if you do not have right set of tools. My experience with memory leak detector tools on windows is bad, sometimes they are not able to correctly instrument the code and some gives you cryptic language output. So I decided to write something. After reading couple of article, in pure C++ environment you can overload operator new and operator delete and this trick can be used to build small tool which would be easy to integrate and find leaks during development. In C language world writing macros which wraps systems calls like malloc/calloc/realloc will help you to find the file name and line number . But in C++, when you do new, it first calls operator new and then the constructors, so macros or pre-processor technique would not be useful.

    But Windows has nice StackWalk64 family of API which could be used to find the exact stack trace for the origin of the call.

    You will need to include following header file in your project and call dumpUnfreedMemory after your application is done.

    For further development on the same watch Memory Tracking On Windows

    #ifndef MEMORY_TRACKER_H_
    #define MEMORY_TRACKER_H_
    
    #pragma warning( disable : 4290 )
    #pragma comment(lib, "Dbghelp.lib")
    
    #include <Windows.h>
    #include <malloc.h>
    #include <DbgHelp.h>
    #include <stdio.h>
    #include <exception>
    
    
    static const int MAX_TRACES = 62;
    static const int MAX_LENGTH = 256;
    static const int BUFFER_LENGTH = (sizeof(SYMBOL_INFO) + MAX_LENGTH * sizeof(wchar_t) + sizeof(ULONG64) - 1) / sizeof(ULONG64); static bool SYSTEM_INITIALIZED = false;
    
    static CRITICAL_SECTION gLock;
    static bool lockInitialized = false;
    
    void Lock() {
      if ( lockInitialized == false ) {
        ::InitializeCriticalSection(&gLock);
        lockInitialized = true;
      }
      ::EnterCriticalSection(&gLock);
    }
    
    void Unlock() {
      ::LeaveCriticalSection(&gLock);
    }
    
    
    typedef struct record_t {
    char symbol[2048];
    char filename[128];
    char linenumber[2048];
      int depth;
    } record;
    
    typedef struct AllocList_t {
    DWORD address;
    DWORD size;
      record *details;
    
      struct AllocList_t* next;
    
    } AllocList;
    
    AllocList *gListHead = NULL;
    
    static void GetCallStackDetails(const void* const* trace, int count, AllocList *newRecord ) {
    for (int i = 0; i < count; ++i) {
    ULONG64 buffer[BUFFER_LENGTH];
    DWORD_PTR frame = reinterpret_cast<DWORD_PTR>(trace[i]);
    DWORD64 sym_displacement = 0;
    PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(&buffer[0]);
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol->MaxNameLen = MAX_LENGTH;
    BOOL has_symbol = SymFromAddr(GetCurrentProcess(), frame, &sym_displacement, symbol);
    DWORD line_displacement = 0;
    IMAGEHLP_LINE64 line = {};
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    BOOL has_line = SymGetLineFromAddr64(GetCurrentProcess(), frame, &line_displacement, &line);
    
        _snprintf (newRecord->details[i].symbol, 2048, "%s", "(No Symbol)");
    
    if (has_symbol) {
          _snprintf (newRecord->details[i].symbol, 2048, "%s", symbol->Name );
    }
    if (has_line) {
          _snprintf (newRecord->details[i].filename, 128, "%s", line.FileName);
          _snprintf (newRecord->details[i].linenumber, 2048, " [%d]", line.LineNumber);
    } else {
          _snprintf (newRecord->details[i].filename, 128, "%s", "Could not determing file name");
          _snprintf (newRecord->details[i].linenumber, 2048, " [%d]", "Could not determine file line");
        }
    }
    }
    
    static void addRecord(void *ptr, size_t size) {
      Lock();
    if ( SYSTEM_INITIALIZED == false ) {
    SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
    if (SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
    SYSTEM_INITIALIZED = true;
    } else {
    SYSTEM_INITIALIZED = false;
    return;
    }
    }
    
      AllocList *newRecord = (AllocList*) malloc ( sizeof ( AllocList ));
      newRecord->next = NULL;
      newRecord->address = (DWORD)ptr;
      newRecord->size = size;
    
      if ( gListHead == NULL ) {
        gListHead = newRecord;
      } else {
        AllocList *current = gListHead;
        while ( current->next != NULL ) {
          current = current->next;
        }
        current->next = newRecord;
      }
    
    void* trace[MAX_TRACES];
    int count = CaptureStackBackTrace(0, MAX_TRACES , trace, NULL);
    
      newRecord->details = ( record *) malloc ( count * sizeof ( record ));
      newRecord->details[0].depth = count;
    
    GetCallStackDetails( trace, count, newRecord);
      
      Unlock();
    }
    
    static void deleteRecord(void *ptr ) {
      Lock();
      AllocList *current, *previous;
      previous = NULL;
      for (current = gListHead; current != NULL; previous = current, current = current->next) {
        if (current->address == (DWORD)ptr) {
          if (previous == NULL) {
            gListHead = current->next;
          } else {
            previous->next = current->next;
          }
          free(current);
          Unlock();
          return;
        }
      }
      Unlock();
    }
    
    void dumpUnfreedMemory(FILE *fp=stderr) {
      Lock();
      AllocList *current;
      int totalBytesNotFreed = 0;
      for (current = gListHead; current != NULL; current = current->next) {
        int depth = current->details[0].depth;
        fprintf ( fp, "Bytes allocated %d not free in following code path\n", current->size );
        totalBytesNotFreed += current->size;
        for ( int i = 0; i < depth ; i++) {
          fprintf ( fp, "%s:%s:%s\n", current->details[i].filename, current->details[i].linenumber, current->details[i].symbol);
        }
        fprintf(fp, "\n");
      }
      fprintf ( fp, "Total bytes not freed %d\n", totalBytesNotFreed );
      Unlock();
    }
    
    // Overloading new operator
    void* operator new ( size_t size ) throw ( std::bad_alloc ) {
    void *ptr = (void *)malloc(size);
    addRecord(ptr, size);
    return ptr;
    }
    // Overloading new[] operator
    void * operator new [] (size_t size) {
      return operator new (size);
    }
    
    // Overloading delete Operator
    void operator delete ( void* ptr ) throw () {
    deleteRecord(ptr);
    free ( ptr );
    }
    
    // Overloading delete[] Operator
    void operator delete [] (void * p) {
      operator delete (p);
    }
    
    #endif
    

    Test program

    #include "MemoryTracker.h"
    void dummyfunc1() {
      char *ptr = new char;
    }
    
    int *dummyfunc2() {
      int *ptr = new int;
      return ptr;
    }
    
    int main ( int argc, char **argv) {
      int *ptr  = new int;
      int *ptr1 = new int;
      int *ptr2 = new int;
    
      delete ptr1;
      //delete ptr2;
      //delete ptr;
    
      dummyfunc1();
      int *ptr3 = dummyfunc2();
      delete ptr3;
    
      dumpUnfreedMemory();
    
      return 0;
    }
    

    After running this your will get output as follows:

    Bytes allocated 4 not free in following code path
    memory_test\memory_test\memorytracker.h: [95]:addRecord
    memory_test\memory_test\memorytracker.h: [137]:operator new
    memory_test\memory_test\memory_test.cpp: [12]:main
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c: [555]:__tmainCRTStartup
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c: [371]:mainCRTStartup
    Could not determing file name: [18512724]:BaseThreadInitThunk
    Could not determing file name: [18512724]:RtlInitializeExceptionChain
    Could not determing file name: [18512724]:RtlInitializeExceptionChain
    
    Bytes allocated 4 not free in following code path
    memory_test\memory_test\memorytracker.h: [95]:addRecord
    memory_test\memory_test\memorytracker.h: [137]:operator new
    memory_test\memory_test\memory_test.cpp: [14]:main
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c: [555]:__tmainCRTStartup
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c: [371]:mainCRTStartup
    Could not determing file name: [18512724]:BaseThreadInitThunk
    Could not determing file name: [18512724]:RtlInitializeExceptionChain
    Could not determing file name: [18512724]:RtlInitializeExceptionChain
    
    Bytes allocated 1 not free in following code path
    memory_test\memory_test\memorytracker.h: [95]:addRecord
    memory_test\memory_test\memorytracker.h: [137]:operator new
    memory_test\memory_test\memory_test.cpp: [3]:dummyfunc1
    memory_test\memory_test\memory_test.cpp: [21]:main
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c: [555]:__tmainCRTStartup
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c: [371]:mainCRTStartup
    Could not determing file name: [18512724]:BaseThreadInitThunk
    Could not determing file name: [18512724]:RtlInitializeExceptionChain
    Could not determing file name: [18512724]:RtlInitializeExceptionChain
    
    Total bytes not freed 9